Я не замечаю ничего плохого в коде 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 иимя уведомления @ "ValuesChanged"?Они действительно должны быть определены как константы, так что есть только одна «истинная» версия строки.Во-первых, это избавляет вас от случая, когда вы случайно ошиблись в одном месте и удивляетесь, почему значения не синхронизируются.Это может занять несколько часов, чтобы понять, что происходит, когда это происходит.(Исходя из опыта здесь.) Во-вторых, компилятор может проверить, что у вас есть правильное имя, и автозаполнение IDE (когда оно действительно работает) может предложить вам ключевые имена.Вы можете сделать #define в общем заголовке где-нибудь
#define kDefaultsKeySelectedCategory @"category"
, и компоновщик , вероятно, создаст один постоянный экземпляр строки, совместно используемой для каждого места, где он используется.Тем не менее, если я изменю строку в этом определении и Xcode будет капризным и не перекомпилирует каждый исходный файл, который его использует, мы вернемся к случаю, когда ключ пишется по-разному в разных местах.Не хорошо.Более причудливый способ сделать это, обеспечивающий только одну копию строки, - объявить
extern NSString* const kDefaultsKeySelectedCategory;
в заголовочном файле, а затем
NSString* const kDefaultsKeySelectedCategory = @"category";
в .m файле.Еще одна вещь, которая мне нравится в этом, это то, что она скрывает детали реализации.Никому не нужно знать, что это за конкретная строка, поэтому ее не должно быть в заголовочном файле.