Coredata - массив fetchedobjects пуст при вызове из другого класса

Из -viewDidLoad() класса UIViewController (называемого StageDetailViewController) я вызываю метод экземпляра другого класса (называемого ContentController).

 - (void)viewDidLoad {
        [super viewDidLoad];
        ContentController * instance = nil;
        instance = [[ContentController alloc] init];
        [instance fetchSectorList];
        [instance release];

       ....other stuff ....

}

Вызываемый метод (fetchSectorList) выглядит так:

- (void)fetchSectorList {

     NSLog(@"fetchSectorList method called");

     NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
                               entityForName:@"Sectors" inManagedObjectContext:self.managedObjectContext];
     [fetchRequest setEntity:entity];
      NSError *error;
      NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];

      for (NSManagedObject *info in fetchedObjects) {
           NSLog(@"aircraft in fetchsectorlist: %@", [info valueForKey:@"aircraft"]);
      }

[fetchRequest release]; 

}

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

Вот проблема: когда я вызываю (void)fetchSectorList из StageDetailViewController, файл NSLog подтверждает, что он был вызван:

"вызван метод fetchSectorList"

... но цикл for ничего не возвращает!

ОДНАКО, когда я вызываю (void)fetchSectorList внутри класса ContentController, цикл for возвращает список «самолетов».

- (NSFetchedResultsController *)stageResultsController {
    [self fetchSectorList];
    return [self resultsControllerForEntity:@"Stage"];
}

Почему же тогда я не могу вызвать этот же метод из другого класса? Пожалуйста помоги. Все вклады очень приветствуются.

Заметки:

1) Я объявляю NSManagedObjectModel, NSManagedObjectContext и NSPersistentStoreCoordinatorin ContentController.h 2) Я унаследовал скелет для основного кода данных из примера в Интернете. Он определяет метод класса, который используется другим классом в примере для инициализации класса.

+ (ContentController *)sharedInstance {
    static ContentController * instance = nil;
    if (!instance) {
        instance = [[ContentController alloc] init];

Однако я выбираю инициализацию из кода инициализатора, показанного выше, в viewdidload() моего вызывающего класса (StageDetailViewController). Может ли это быть частью проблемы?

Спасибо за терпеливость. Я был бы очень признателен за некоторый вклад здесь. Я был бы рад предоставить разъяснения по любому из вышеперечисленных.

Решение!!!

Ребята, спасибо за все советы. Следуя комментариям Маркуса, я немного углубился в синглтоны, и вызов, который дает желаемый результат от StageDetailViewController в -viewdidload(), выглядит просто:

[[Общий экземпляр контроллера содержимого] fetchSectorList];

Синглтон в моем приложении:

  • (ContentController *) общий экземпляр

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

Маркус, извините, что связываю ваше имя с Одиночками... Я обещаю расширить свой арсенал на более позднем этапе.


person Lee Barringer    schedule 03.01.2012    source источник
comment
Я предлагаю вам отметить ответ как правильный или добавить свой собственный и отметить его как правильный. В противном случае этот вопрос останется открытым и в конечном итоге зачтется против вас.   -  person Marcus S. Zarra    schedule 04.01.2012
comment
Спасибо, Маркус. Я попытался это сделать сразу после получения решения, но сайт не позволил мне сделать это в течение 8 часов после регистрации проблемы ... поскольку я новый пользователь. Попробую еще раз сейчас.   -  person Lee Barringer    schedule 05.01.2012


Ответы (3)


Во-первых, не используйте синглтоны. Потратьте время, чтобы узнать о схемах внедрения зависимостей.

Во-вторых, вы неправильно используете синглтон.

- (void)viewDidLoad {
        [super viewDidLoad];
        ContentController * instance = nil;
        instance = [[ContentController alloc] init];
        [instance fetchSectorList];
        [instance release];

       ....other stuff ....

}

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

Измените этот код на:

- (void)viewDidLoad {
        [super viewDidLoad];
        ContentController * instance = [ContentController sharedInstance];
        [instance fetchSectorList];

       ....other stuff ....

}

И вы получите желаемые результаты, я подозреваю.

Обновление 1

У вас есть что-нибудь в постоянном магазине?

self.managedObjectContext возвращает фактический объект или это ноль?

person Marcus S. Zarra    schedule 03.01.2012
comment
Привет, Маркус, спасибо за ваши комментарии. Очень признателен. Я запустил исправленный одноэлементный код (замечания отмечены!) И, к сожалению, он сделал то же самое, что и раньше: был вызван метод :remote, но в цикле for не было возвращено никаких значений. - person Lee Barringer; 03.01.2012
comment
Ответ @LeeBarringer обновлен некоторыми вопросами для отладки. - person Marcus S. Zarra; 03.01.2012
comment
Маркус, спасибо. Я проверил это, поместив простой if (self.managedobjectcontext != nil){...} вокруг NSLog, и в обоих случаях (пустой и полный массив) self.managedobjectcontext НЕ был нулевым. Тотальная головная боль. - person Lee Barringer; 04.01.2012
comment
Привет, Маркус, нашел решение... см. строку с описанием проблемы... спасибо за помощь! Очень признателен. - person Lee Barringer; 04.01.2012

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

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

person jrturton    schedule 03.01.2012
comment
Спасибо за это. Я разместил точки останова в коде для двух случаев, и контекст управляемого объекта в каждом случае выглядел одинаково. К сожалению, я не могу публиковать изображения, так как этот веб-сайт не позволяет новым пользователям загружать их по причинам спама :-( ... Единственная разница, конечно, заключалась в том, что массив в успешном случае состоял из двух элементов, а в неудачном случае - нет членов ... - person Lee Barringer; 04.01.2012
comment
Вероятно, это мое невежество, как новичка, но когда я выделяю инициализацию ContentController, я думал, что автоматически получу контекст управляемого объекта? Контекст объявляется в заголовке и реализуется как метод ContentController. - person Lee Barringer; 04.01.2012
comment
Привет!, решение найдено... см. в описании проблемы... спасибо за помощь! Очень признателен - person Lee Barringer; 04.01.2012

Спасибо за все советы. Следуя комментариям Маркуса, я немного углубился в синглтоны, и вызов, который дает желаемый результат от StageDetailViewController в -viewdidload(), выглядит просто:

[[Общий экземпляр контроллера содержимого] fetchSectorList];

Синглтон в моем приложении:

  • (ContentController *) общий экземпляр

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

Маркус, извините, что связываю ваше имя с Одиночками... Я обещаю расширить свой арсенал на более позднем этапе.

person Lee Barringer    schedule 05.01.2012