2012-02-23 2 views
0

Я пытаюсь сохранить некоторые данные и перезвонить в виде таблицы с другого контроллера, но он не работает. Я как-то теряю значение переменной, так как категория var изменяется до нуля, когда я меняю ее в контроллере представления, любой из них.NSUserDefaults not saving

В моей NewEntry.m у меня есть:

-(IBAction)saveButton:(id)sender {  

    int i = selectedSegment.selectedSegmentIndex;  

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults]; 

    [userDefaults setInteger:i forKey:@"category"]; 

    [userDefaults synchronize]; 

    if (selectedSegment.selectedSegmentIndex == 0) { 
     [userDefaults setObject:titlefield.text forKey:@"titletexthomework"]; 
     [userDefaults setObject:detailstextfield.text forKey:@"detailshomework"]; 
    } 
    else if(selectedSegment.selectedSegmentIndex == 1) { 
     [userDefaults setObject:titlefield.text forKey:@"titletextprojects"]; 
     [userDefaults setObject:detailstextfield.text forKey:@"detailsprojects"]; 

    } 
    else if (selectedSegment.selectedSegmentIndex == 2){ 
     [userDefaults setObject:titlefield.text forKey:@"titletextappointments"]; 
     [userDefaults setObject:detailstextfield.text forKey:@"detailsappointments"]; 
    } 
    else if (selectedSegment.selectedSegmentIndex == 3){ 
     [userDefaults setObject:titlefield.text forKey:@"titletextevents"]; 
     [userDefaults setObject:detailstextfield.text forKey:@"detailsevents"]; 

    } 

    else if (selectedSegment.selectedSegmentIndex == 4){ 
     [userDefaults setObject:titlefield.text forKey:@"titletexttodolist"]; 
     [userDefaults setObject:detailstextfield.text forKey:@"detailstodolist"]; 
    } 

    [userDefaults synchronize]; 
    NSLog(@"selected segment %i", i); 
} 

тогда в моей Projects.m у меня есть:

-(void)viewDidLoad 
{ 
    [super viewDidLoad];  

    categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:@"category"]; 
    NSLog(@"category selected %i", categoryselected);   

    titlestring = [[NSUserDefaults standardUserDefaults] objectForKey:@"titletextprojects"]; 
    detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:@"detailsprojects"];   

    tabledata = [[NSArray alloc] initWithObjects:titlestring, nil]; 
    tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil];  
} 

//------------------------------------------------------- 
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 
{  
    UITableViewCell *cell = nil; 

    cell = [tableView dequeueReusableCellWithIdentifier:@"projectscell"]; 

    if(cell == nil) { 
     cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"projectscell"]; 
    } 

    cell.textLabel.text = [tabledata objectAtIndex:indexPath.row]; 
    cell.detailTextLabel.text = [tablesubtitles objectAtIndex:indexPath.row]; 
    cell.textLabel.font = [UIFont systemFontOfSize:14.0]; 
    cell.textLabel.backgroundColor = [ UIColor clearColor ]; 
    cell.detailTextLabel.backgroundColor = [UIColor clearColor]; 

    return cell; 
} 

** * ** * *ОБНОВЛЕНИЕ* ** * ** * ** * ** * *

Я изменил ту часть, которая заполняет таблицу на статическую строку, как это:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; 
{ 
tabl = [[NSArray alloc] initWithObjects:@"hello", nil]; 
NSLog(@"tabledata %@", tabledata); 
tab = [[NSArray alloc] initWithObjects:@"hello2", nil]; 
NSLog(@"details %@", tablesubtitles); 



UITableViewCell *cell = nil; 

cell = [tableView dequeueReusableCellWithIdentifier:@"projectscell"]; 


if(cell == nil) 
{ 
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"projectscell"]; 

} 
cell.textLabel.text = [tabl objectAtIndex:indexPath.row]; 
cell.detailTextLabel.text = [tab objectAtIndex:indexPath.row]; 
cell.textLabel.font = [UIFont systemFontOfSize:14.0]; 
cell.textLabel.backgroundColor = [ UIColor clearColor ]; 
cell.detailTextLabel.backgroundColor = [UIColor clearColor]; 

а также таблица по-прежнему отображается пустым. Спасибо за помощь.

+1

Это, вероятно, не ваша проблема, но это стоит знать и устранять ее. Любые последние изменения в NSUserDefaults не сохраняются, если вы «остановите» процесс из XCode. Если вы сначала нажмете кнопку «домой», а затем «Стоп», они должны быть сохранены. – Max

+0

Alec - Это хороший момент, но 'synchronize' гарантирует, что обновления будут записаны на диск. – Justin

+0

Попробуйте отладить код? Ваше действие уволено? Вы подключили IBAction? Вам не нужно синхронизировать два раза. Затем, в зависимости от стиля, почему бы вам не использовать 'i' вместо' selectedSegment.selectedSegmentIndex' в операциях 'if-else if'. –

ответ

1

Я не замечаю ничего неправильного в коде NSUserDefaults, по сути, хотя он только захватывает значения при загрузке представления, а не когда значения обновляются. Чтобы исправить это, вы можете отправить уведомление, чтобы все другие заинтересованные контроллеры представлений знали о смене состояния. В - [NewEntry SaveButton:], после сохранения значения в NSUserDefaults, добавьте

[[NSNotificationCenter defaultCenter] postNotificationName:@"ValuesChanged" 
                object:self]; 

отправить уведомление. Где-то в Projects.m (INIT это хорошее место), подписаться на уведомление с

[[NSNotificationCenter defaultCenter] addObserver:self 
             selector:@selector(valuesChanged:) 
              name:@"ValuesChanged" 
              object:nil]; 

Это приводит к тому, центр уведомлений перезвонить на ваш valuesChanged: метод, когда уведомление опубликовано. Мы будем обновлять пользовательский интерфейс в значительной степени тем же, как мы делали в viewDidLoad, так что давайте учитывать, что код из:

- (void)reloadData 
{ 
    categoryselected = [[NSUserDefaults standardUserDefaults] integerForKey:@"category"]; 
    NSLog(@"category selected %i", categoryselected); 

    // XXX - note the following strings are returned autoreleased. If they're 
    // stored in ivars, it's a good idea to retain them, even though we know 
    // they're retained by the arrays below. 

    titlestring = [[NSUserDefaults standardUserDefaults] objectForKey:@"titletextprojects"]; 
    detailsstring = [[NSUserDefaults standardUserDefaults] objectForKey:@"detailsprojects"]; 

    [tabledata release]; 
    tabledata = [[NSArray alloc] initWithObjects:titlestring, nil]; 

    [tablesubtitles release]; 
    tablesubtitles = [[NSArray alloc] initWithObjects:detailsstring, nil]; 

    [tableView reloadData]; 
} 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    [self reloadData]; 
} 

- (void)valuesChanged:(NSNotification*)notification 
{ 
    [self reloadData]; 
} 

Одна последняя вещь: все эти строки, ключи для NSUserDefaults и уведомления name @ "ValuesChanged"? Они действительно должны быть определены как константы, так что существует только одна «истинная» версия строки. Во-первых, это избавляет вас от случая, когда вы случайно ошибаетесь в одном месте и задаетесь вопросом, почему значения не синхронизируются. Это может занять несколько часов, чтобы выяснить, что происходит, когда это произойдет. (Говоря об опыте здесь.) Во-вторых, компилятор может проверить, что у вас есть правильное имя, и автозаполнение IDE (когда оно действительно работает) может предложить вам ключевые имена. Вы можете сделать #define в общем заголовке где

#define kDefaultsKeySelectedCategory @"category" 

и компоновщик вероятно создать единый постоянный экземпляр строки разделяемой между каждым местом он используется.Тем не менее, если я изменяю строку в этом определении, а Xcode является неустойчивым и не перекомпилирует каждый исходный файл, который его использует, мы вернемся к случаю, когда ключ пишется по-разному в разных местах. Не хорошо. Любитель способ сделать это, что гарантирует, что только одна копия строки является объявить

extern NSString* const kDefaultsKeySelectedCategory; 

в заголовочном файле, а затем

NSString* const kDefaultsKeySelectedCategory = @"category"; 

в файле .m. Еще одна вещь, которая мне нравится в этом способе, - это скрытие деталей реализации. Никто не должен знать, что такое конкретная строка, поэтому она не должна находиться в файле заголовка.

+0

tableview не работает, он спрашивает, имел ли я значение UITableView, но это не работает. – user1191343

+0

самозагружаемые данные не работают. – user1191343

+0

ОК, я изменил массив с titlestring и detailsstring на @ "hello", и ничего не выводит, поэтому это не NSUserDefaults – user1191343

3

Вызовите синхронизацию ПОСЛЕ установки любых значений.

0

У меня была такая же проблема, когда я тестировал свое приложение, где, если я использую Stop в отладчике, а затем повторно запускаю приложение, NSUserDefaults неправильно отображали старый список. Это не произошло с операцией Insert, но с Delete.

Если я использую кнопку «домой» для выхода из приложения (убейте его), а затем перезапустите, мои NSUserDefaults верны.

Alec Feb 23 '12 в 17:13 также упомянули это в более раннем комментарии.

0

У меня возникла проблема с настройкой NSUserDefaults, даже если вы используете команду synchronize сразу после. Моя проблема была в том, что приложение было переименовано, и я считаю, что NSUserDefaults не синхронизировали местоположение правильно. Я удалил приложение и переустановил его из Xcode, и он сработал. Я предполагаю, что это немного особый случай, но если что-нибудь попробует.