我应该注意调试这个Core-Data / NSFetchedResultsController错误?

时间:2010-12-01 18:19:26

标签: iphone uitableview core-data nsfetchedresultscontroller

我的核心数据实现中有一个错误,我似乎无法掌握,我需要一些关于我应该在哪里找出解决方法的提示。

长话短说,我UITableView填充NSFetchedResultsController。我希望我的用户能够更改数据的排序选项,因此我给他们一个选择器,将基础fetchedResultsController更改为不同的预设配置。我可以在不同的fetchedResultsControllers之间来回切换,没有任何问题。我可以添加和删除数据,从不遇到任何崩溃,没问题。但是,在fetchedResultController配置的2(6个,总是相同的2)中,添加到数据库的项目不会添加到tableview中。一旦编辑,tableview中的项目就会消失。

以下是我重现错误的步骤:

  1. 将排序设置为有效的配置
  2. 向数据库添加新项目(此时controllerWillChangeContent已开火)
  3. 更改为无效的配置
  4. 向数据库添加新项目(controllerWillChangeContent不会触发)
  5. 切换回工作配置
  6. 现在可以在tableView
  7. 中看到添加的项目
  8. 切换回非工作配置
  9. 该项目现在显示在tableView
  10. 修改项目(controllerWillChangeContent已被触发,但controller:DidChangeObject:的类型为NSFetchedResultsChangeDelete而非NSFetchedResultsChangeUpdate
  11. 更改回工作配置,项目会更改并再次显示。
  12. 我对这件事情有所了解。我完全没有想法。创建这两个fetchedResultsControllers的方式与其他4个方式之间几乎没有区别。 可以提供的任何帮助非常赞赏。

    - 编辑 -

    还有一些问题。重申一些TechZen问题的答案:

    • 我的所有属性都未设置为瞬态值
    • 我现在正在使用扁平模型。它是具有直接属性的单个实体。没有关系。
    • 缓存设置为nil
    • 时问题仍然存在
    • 我在每次更改前将旧frc的委托设置为nil,并在切换结束时将新frc的委托设置为self 。所有6 frc s
    • 都是一致的
    • 每次用户切换到其他排序选项时,我都会发布旧版frc并创建一个新版本。

    对于那些感兴趣的人,我用来切换frc的代码在一个要点here

    - 编辑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 个答案:

答案 0 :(得分:1)

我根据要求将此评论作为答案重新发布。

“作业”和“位置”属性都是可选的。您在其中一个损坏的配置中添加的新项目是否实际包含这些属性的值?可能是项目未添加到表中,因为由于其属性值和NSFetchedResultsController设置,根本不会提取它。出于同样的原因,可能是,一旦编辑,一个项目就会从表格中消失(因为它在编辑后不再属于该表格)。

编辑

要设置与nil不同的初始值,请在Core Data Person.m文件中添加以下方法

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

等。这样,每次创建新的人物对象时,Core Data都会自动插入初始值。

答案 1 :(得分:0)

这可能是FRC缓存的问题。尝试将它们全部设置为nil并查看它是否结算。

这可能是瞬态属性的问题。我注意到使用瞬态属性的提取有时会表现得很奇怪。

然而,更可能的是,分配FRC代表似乎是一个问题。如果UI控制器收到FRC委托消息,则新的或编辑的对象将仅出现在UI中。看起来他们没有可靠地接收委托消息。

如果未使用的FRC仍处于活动状态且仍然设置了其委托,那么您可能会在其与委托的消息之间发生冲突。对来自任何源的持久性存储的任何更改都可能触发任何FRC触发委托消息。命中代表的消息可能不是来自您打算处于活动状态的FRC。

确保未使用的FRC设置了nil委托。