Что я должен смотреть, чтобы отладить эту ошибку Core-Data / NSFetchedResultsController? - PullRequest
2 голосов
/ 01 декабря 2010

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

Короче говоря, у меня есть UITableView, заполненный NSFetchedResultsController. Я хочу, чтобы мои пользователи могли изменять параметры сортировки данных, поэтому я предоставляю им средство выбора, которое изменит базовый fetchedResultsController на другие предустановленные конфигурации. Я могу переключаться между различными fetchedResultsControllers без каких-либо проблем. Я могу добавлять и удалять данные, никогда не происходит сбоев, никаких проблем. Однако в 2 (из 6 и всегда одинаковых 2) конфигурациях fetchedResultController элементы, добавленные в базу данных, не добавляются в представление таблицы. И элементы, которые находятся в виде таблицы, исчезают после редактирования.

Вот шаги, которые я прошёл, чтобы воспроизвести ошибку:

  1. Установить сортировку для конфигурации, которая работает
  2. Добавить новый элемент в базу данных (в этот момент controllerWillChangeContent срабатывает)
  3. Изменить конфигурацию, которая не работает
  4. Добавить новый элемент в базу данных (controllerWillChangeContent не срабатывает)
  5. Переключиться обратно в рабочую конфигурацию
  6. Добавленный предмет теперь виден в tableView
  7. Переключиться обратно на нерабочую конфигурацию
  8. Предмет теперь виден в tableView
  9. Редактировать элемент (controllerWillChangeContent запускается, но controller:DidChangeObject: запускается с типом NSFetchedResultsChangeDelete вместо NSFetchedResultsChangeUpdate)
  10. Вернитесь к рабочей конфигурации, и элемент будет изменен и снова виден.

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

- EDIT -

По-прежнему возникают некоторые проблемы с этим. Чтобы повторить некоторые ответы на вопросы TechZen:

  • Ни один из моих атрибутов не установлен в качестве переходных значений
  • Я сейчас использую плоскую модель. Это единое целое с прямыми атрибутами. Там нет никаких отношений.
  • Проблема сохраняется с кэшем, установленным на nil
  • Я устанавливаю старый делегат frc на nil перед каждым изменением и устанавливаю нового делегата frc на self в конце коммутатора. Это верно для всех 6 frc с
  • Я выпускаю старую frc и создаю новую каждый раз, когда пользователь переключается на другую опцию сортировки.

Для тех, кто заинтересован, код, который я использую для переключения frc, находится в сущности здесь

- РЕДАКТИРОВАТЬ 2 -

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

- Редактировать 3 -

По запросу, вот код для моих методов делегата:

-(void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView beginUpdates];
}

-(void)controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
            break;

    }
}

-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
    switch (type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeDelete:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
        case NSFetchedResultsChangeUpdate:
            if (!self.searchIsActive) {
                [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
            } else {
                [self.searchDisplayController.searchResultsTableView reloadData];
            }
            break;
        case NSFetchedResultsChangeMove:
            [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
            [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
            break;
    } 
}


-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
    [self.tableView endUpdates];

}

И информация получила мою модель данных:

// Person.h
#import <CoreData/CoreData.h>
@interface Person :  NSManagedObject  
{
}

@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * company;
@property (nonatomic, retain) NSString * comments;
@property (nonatomic, retain) NSString * job;
@property (nonatomic, retain) NSDate * logDate;
@property (nonatomic, retain) NSString * location;
@property (nonatomic, retain) NSNumber * rating;
@property (nonatomic, retain) NSString * imagePath;
@property (nonatomic, retain) NSString * thumbPath;

@end

// Person.m
#import "Person.h"

@implementation Person 

@dynamic name;
@dynamic company;
@dynamic comments;
@dynamic job;
@dynamic logDate;
@dynamic location;
@dynamic rating;
@dynamic imagePath;
@dynamic thumbPath;

@end

Информация о модели данных:

Entity: Person
    Property: comments
        kind: attribute
        type: string
        optional: YES
    Property: name
        kind: attribute
        type: string
        optional: NO
    Property: rating
        kind: attribute
        kind: Int 16
        optional: YES
        min value: 0
        max value: 5
    Property: job
        kind: attribute
        kind: string
        optional: YES
    Property: company
        kind: attribute
        kind: string
        optional: YES
    Property: location
        kind: attribute
        kind: string
        optional: YES
    Property: imagePath
        kind: attribute
        kind: string
        optional: YES
    Property: thumbPath
        kind: attribute
        kind: string
        optional: YES
    Property: logDate
        kind: attribute
        kind: date
        optional: YES

Ничего особенного в этом нет.

Ответы [ 2 ]

1 голос
/ 10 декабря 2010

Я отправляю этот комментарий как ответ на запрос.

Оба атрибута "job" и "location" являются необязательными. Содержит ли новый элемент, добавленный в одну из поврежденных конфигураций, значения для этих атрибутов? Может случиться так, что элемент не добавляется в таблицу, потому что из-за значений его атрибутов и настройки NSFetchedResultsController он просто не выбирается вообще. По тем же причинам может оказаться, что после редактирования элемент исчезнет из таблицы (поскольку он больше не принадлежит таблице после редактирования).

РЕДАКТИРОВАТЬ :

Чтобы установить начальное значение, отличное от nil, в файле Core Data Person.m добавьте следующий метод

- (void) awakeFromInsert{
    self.job = @"";
    self.location = @"";
}

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

0 голосов
/ 01 декабря 2010

Это может быть проблема с кешами FRC.Попробуйте установить их все в ноль и посмотреть, разрешится ли это.

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

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

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

Убедитесь, что у FRC, который не используется, установлен нулевой делегат.

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