Общий источник данных Singleton в Objective-C

Эй, ребята, я пишу довольно простое приложение для iPhone. Данные поступают из plist-файла (в основном NSDictionary), который я пытаюсь загрузить в одноэлементный класс и использовать на разных контроллерах представления для доступа к данным.

Вот реализация для моего синглтона (в значительной степени смоделирована после этого потока )

@implementation SearchData

@synthesize searchDict;
@synthesize searchArray;

- (id)init {
    if (self = [super init]) {
        NSString *path = [[NSBundle mainBundle] bundlePath];
        NSString *finalPath = [path stringByAppendingPathComponent:@"searches.plist"];
        searchDict = [NSDictionary dictionaryWithContentsOfFile:finalPath];
        searchArray = [searchDict allKeys];
    }

    return self;
}

- (void)dealloc {
    [searchDict release];
    [searchArray release];
    [super dealloc];
}

static SearchData *sharedSingleton = NULL;

+ (SearchData *)sharedSearchData {
    @synchronized(self) {
        if (sharedSingleton == NULL)
            sharedSingleton = [[self alloc] init];
    }   
    return(sharedSingleton);
}

@end

Поэтому всякий раз, когда я пытаюсь получить доступ к свойствам searchDict или searchArray в другом месте моего приложения (например, делегат TableView), примерно так:

[[[SearchData sharedSearchData] searchArray] objectAtIndex:indexPath.row]

Я получаю исключение о том, что *** - [NSCFSet objectAtIndex:]: нераспознанный селектор отправлен на экземпляр 0x5551f0

Я не совсем уверен, почему сообщение objectAtIndex отправляется объекту NSCFSet, я чувствую, что мой синглтон реализован неправильно или что-то в этом роде. Я также попробовал более сложную реализацию синглтона, такую ​​как рекомендованная Apple в вышеупомянутой теме, и у меня была та же проблема. Спасибо за любую информацию, которую вы можете предоставить.

10.12.2008 08:49:44
3 ОТВЕТА
РЕШЕНИЕ

В вашем -initметоде вы напрямую обращаетесь к переменным вашего экземпляра и не сохраняете их. Они освобождаются, и их память используется другими объектами позже при жизни вашего приложения.

Либо сохраните свои объекты, которые вы там создаете, либо используйте не удобные методы для их создания.

searchDict = [[NSDictionary alloc] initWithContentsOfFile:finalPath];
searchArray = [[searchDict allKeys] retain];
11
10.12.2008 08:59:14
Спасибо Эшли, сохранение переменных исправило это. Как продолжение - какова цель (не атомарная, сохранить) в моем объявлении @property. Я предполагал, что сохранение означает, что свойства будут автоматически сохранены.
Andy Bourassa 10.12.2008 19:33:42
Теги в определении @property определяют, как работают методы доступа. В случае (не атомарный, сохраняемый) они не синхронизируются между несколькими потоками и сохраняют назначаемый объект (который в любом случае является атомарным по своей природе IIRC). Вы прямо присваивали переменные, минуя их.
Ashley Clark 10.12.2008 19:59:30
Смотрите мой комментарий к другому ответу о том, почему вы не должны использовать синтаксис self.variable в ваших методах -init и -dealloc. Короткий ответ: нежелательные побочные эффекты.
Ashley Clark 10.12.2008 20:01:48

Всякий раз, когда вы назначаете синтезированные переменные, делайте это через 'self', поэтому:

- (id)init {
  if (self = [super init]) {
      NSString *path = [[NSBundle mainBundle] bundlePath];
      NSString *finalPath = [path stringByAppendingPathComponent:@"searches.plist"];
      self.searchDict = [NSDictionary dictionaryWithContentsOfFile:finalPath];
      self.searchArray = [searchDict allKeys];
  }

  return self;

}

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

1
10.12.2008 14:02:21
Apple особо рекомендует не использовать методы in -init, поскольку ваши сеттеры могут иметь побочные эффекты с условиями, которые еще не выполнялись во время инициализации объекта.
Ashley Clark 10.12.2008 20:00:23
Я должен также добавить, что они советуют против этого в -dealloc также по тем же причинам.
Ashley Clark 10.12.2008 20:00:55

Привет, Можете ли вы сказать мне, в чем преимущество, когда мы присваиваем синтезированные переменные через «я»? Спасибо Шива

значения устанавливаются через установщик; он освобождает предыдущее значение и сохраняет тот, который вы назначаете.

0
3.08.2009 08:49:25