Coredata - «NSObjectInaccessibleException - CoreData не может выполнить ошибку» - PullRequest
32 голосов
/ 08 апреля 2011

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

Проблема заключается в следующем

У меня есть два представления, которые получают данные с сервера и обновляют интерфейс.Я настроил поток следующим образом:

view1 -> Отправка HTTP-запроса с сервера - Получение обратного вызова -> Сохранение данных в Coredata -> Чтение из базовых данных и отображение в пользовательском интерфейсе (обратный вызов и сохранение / чтение Coredata происходятв ViewController)

view2 -> отправка HTTP-запроса с сервера - получение обратного вызова -> сохранение данных в Coredata -> чтение из базовых данных и отображение в пользовательском интерфейсе (обратный вызов и сохранение / чтение Coredata происходят во ViewController)

Представление 2 повторяет этот процесс каждые 3 секунды, поскольку это экран автоматического обновления.

Проблема заключается в том, что всякий раз, когда я пытаюсь переключаться между представлениями 1 и 2 очень быстро, происходит сбой приложения с указанной выше ошибкой.Если я подожду несколько секунд на каждом просмотре (подождите, пока данные будут извлечены с сервера), он будет работать нормально.Я делаю что-то не так, что мне нужно изменить?

- (void) refreshData {
    [super refreshData];
    [[UserDataFactory sharedSingleton] refreshLoggedInUserDataAndRespondTo:self user:self.user];
}

- (BOOL) refreshDataCallback:(QExtendedHTTPOperation*)responseOperation {
    [self saveToCoreData: responseOperation.responseArray];
    NSMutableArray *tmp = [[NSMutableArray alloc] initWithArray:[self readFromCoreData]];
    [self setData: tmp];
    [tmp release];
    [self.tableView reloadData];
    return YES;
}

- (void) saveToCoreData:(NSArray *) responseArray{
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
    [fetchRequest setEntity:entity];
    [fetchRequest setReturnsObjectsAsFaults:NO];
    NSError *error;
    NSArray *items = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
    [fetchRequest release];

    for (NSManagedObject *managedObject in items) {
            [self.managedObjectContext deleteObject:managedObject];
    }

    for (int i=0; i<[responseArray count]; i++) {
            CoreView1 *coreView1_ = [NSEntityDescription insertNewObjectForEntityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
            coreView_.id = [[responseArray objectAtIndex:i] id];    
            [self.managedObjectContext insertObject:coreView1_];
    }
    [self saveContext:self.managedObjectContext];
}

- (NSArray *) readFromCoreData{ 
    NSEntityDescription *entity = [NSEntityDescription entityForName:@"CoreView1" inManagedObjectContext:self.managedObjectContext];
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:entity];
    [fetchRequest setReturnsObjectsAsFaults:NO];
    NSError *error;
    NSMutableArray *fetchedObjects = [[self.managedObjectContext executeFetchRequest:fetchRequest error:&error] mutableCopy];
    [fetchRequest release];
    return [fetchedObjects autorelease];
}

Это пример кода, который я использую, даже View2 имеет те же обратные вызовы и следует тому же потоку.

Редактировать 1 Забыл упомянуть об этом раньше, я всегда получаю ошибку в методе saveToCoreData.Кроме того, еще одна вещь, на которую следует обратить внимание: если я удаляю код для удаления объектов, все работает нормально (мне нужно удалить все существующие данные из таблицы перед сохранением обновленных данных).Не уверен, что происходит, хотя.

Ответы [ 4 ]

42 голосов
/ 20 апреля 2011

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

Итак, чтобы решить эту проблему и все же удалить ваши данные, вы должны заставить ваши представления прослушивать уведомления NSManagedObjectContextWillSaveNotification и / или NSManagedObjectContextDidSaveNotification и обновлять вашипросмотры с самыми последними версиями данных в вашем магазине.Именно в этот момент вы должны выбросить все объекты Core Data, за которыми хранятся ваши представления, и перезагрузить их из хранилища.

3 голосов
/ 04 января 2013

Я только что исправил эту ошибку в своем коде.Кажется, мой кэш был каким-то образом поврежден.Я воспользовался предложением Кристофера Пикслея и Кейла Гилларда об удалении или переименовании моего кэша, и вуаля, сбой разрешен. NSFetchedResultsController index за пределами

0 голосов
/ 29 сентября 2011

Для информации вчера у меня была такая же ошибка. Я проверил в живую версию приложения, и оно все еще было там. Хлоп.

Я пробежал все варианты добавления информации в основной стек данных, пока не произошел сбой.

Затем я посмотрел файл sqlite из приложения в библиотеке симулятора с помощью SqliteManager. Я нашел ошибку данных в одной таблице. Это произошло из-за того, что при первом запуске приложения использовалась стартовая база данных. Ошибка была в стартовом дБ.

Запустите приложение снова, проверяя каждое поле в каждой таблице. Найдено еще несколько случаев. Я помню, как читал этот вопрос, и подумал, что, возможно, кто-то еще может извлечь выгоду из моей ошибки.

0 голосов
/ 08 апреля 2011

Ваше чрезмерное высвобождение fetchedObjects в вашем readFromCoreData методе. executeFetchRequest вернет вам автоматически выпущенные объекты в любом случае. Когда текущий цикл выполнения завершает выполнение (когда вы переходите из представлений), он пытается дважды выпустить объекты (при условии, что вы не использовали свои собственные пулы автоматического выпуска).

Я бы изменил

return [fetchedObjects autorelease]; 

до

return fetchedObjects;
...