Почему NSFetchedResultsController executeFetch: сбой при воссоздании NSFetchedResultsController с эквивалентным NSFetchRequest? - PullRequest
4 голосов
/ 06 октября 2009

Почему происходит сбой [NSFetchedResultsController performFetch:] при воссоздании NSFetchedResultsController с эквивалентным NSFetchRequest?

У меня есть приложение, в котором есть контроллер табличного представления потоков (потоков сообщений). Когда вы нажимаете на поток, он загружает другой контроллер табличного представления, который использует NSFetchedResultsController, чтобы получить все сообщения этого потока и отобразить их. Я использую NSFetchedResultsController, потому что я могу загружать сообщения в фоновом режиме / удалять / добавлять новые и вообще не беспокоиться об их отображении.

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

Вот шаги по воспроизведению CRASH:

  1. Нажмите на ветку, чтобы она показала мне сообщения.
  2. Перезагрузите сообщения, чтобы NSFetchedResultsController привык к отображению новых сообщений.
  3. Вернуться назад.
  4. Нажмите на другую тему.
  5. Вернуться назад.
  6. Нажмите на первую тему.

При нажатии создается NSFetchedResultsController, идентичный самому первому. (Тот же кеш и все). Вместо того, чтобы работать как следует, он выдает эту ошибку и вылетает:

Program received signal: “EXC_BAD_ACCESS”.

NSFetchedResultsController отправляет сообщение освобожденному объекту.

Вот трассировка стека:

#0  0x95ffd688 in objc_msgSend
#1  0x0060699b in -[NSFetchedResultsController(PrivateMethods) _computeSectionInfo:error:]
#2  0x00601bf0 in -[NSFetchedResultsController performFetch:]
#3  0x0001c170 in -[CMNewMessagesViewController loadMessagesViewControllerForThread:showProfile:] at CMNewMessagesViewController.m:331

3 - мой метод

Есть идеи вообще? Любая помощь будет высоко ценится.


РЕШИТЬ!

Это была моя вина. Я использовал sectionNameKeyPath, который был получен из другого значения ключа. Это нормально, если NSFetchRequest отсортирован по этому значению ключа. Проблема заключалась в том, что он генерировался динамически, поскольку я не хотел тратить на это место в БД. Я использовал переменную экземпляра в классе NSManagedObject, которая была очищена с помощью didTurnIntoFault.

Теперь я думаю, что переменная экземпляра должна была быть создана, затем отброшена, а затем воссоздана в какой-то момент, что привело к остановке сортировки NSFetchedResultsController.

Это объясняет, почему проблема не решена с помощью sectionNameKeyPath или делегата.

Теперь я переключился на сохраненное значение ключа в CoreData Object, и, похоже, он работает просто отлично.

Ответы [ 2 ]

1 голос
/ 03 февраля 2011

При вызове executeFetch я получил тот же самый сигнал EXC_BAD_ACCESS очень глубоко в системном стеке. Изменения с кешем или чем-то не помогли.

- (void)viewDidLoad {
    [super viewDidLoad];

    MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
    managedContext = [appDelegate managedObjectContext];

    NSError *error = nil;
    NSFetchedResultsController *frC = self.fetchedResultsController;
    if (![frC performFetch:&error]) {
        /* */
    }
}

В последнее время я нашел один небольшой фрагмент для добавления. На самом деле, проблема заключалась в том, как я использовал управление памятью iOS (или не использовал).

- (NSFetchedResultsController *)fetchedResultsController {
    if (fetchedResultsController != nil) {
        return fetchedResultsController;
    }

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Asiakasrekisteri" inManagedObjectContext:managedContext]; [fetchRequest setEntity:entity];

    [fetchRequest setFetchBatchSize:200];

    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"yritys" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];

    [fetchRequest setSortDescriptors:sortDescriptors];

    NSFetchedResultsController *aFetchedResultsController =
        [[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedContext sectionNameKeyPath:nil cacheName:nil] retain];

    aFetchedResultsController.delegate = self;
    self.fetchedResultsController = aFetchedResultsController;

    [aFetchedResultsController release];
    [fetchRequest release];
    [sortDescriptor release];
    [sortDescriptors release];  
    return fetchedResultsController;
} 

aFetchedResultsController имел очень короткую независимую жизнь, но он был освобожден до выполнения executeFetch retain помогло, а контроллер результатов выделен.

0 голосов
/ 29 августа 2011

Это была моя вина. Я использовал sectionNameKeyPath, который был получен из другого значения ключа. Это нормально, если NSFetchRequest отсортирован по этому значению ключа. Проблема заключалась в том, что он генерировался динамически, поскольку я не хотел тратить на это место в БД. Я использовал переменную экземпляра в классе NSManagedObject, которая была очищена с помощью didTurnIntoFault.

Теперь я думаю, что переменная экземпляра должна была быть создана, затем отброшена, а затем воссоздана в какой-то момент, и сортировка NSFetchedResultsController остановилась.

Это объясняет, почему проблема не решена с помощью sectionNameKeyPath или делегата.

Теперь я переключился на сохраненное значение ключа в объекте CoreData, и, похоже, он работает просто отлично.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...