代码之家  ›  专栏  ›  技术社区  ›  Drew C

基于控件的表视图在实体的第二次插入时总是失败

  •  5
  • Drew C  · 技术社区  · 15 年前

    我正在使用nsfetchedresultsController管理在具有一个部分的表视图中显示提取的托管对象。表以空开头,用户可以使用UI向其添加新实体。事实上,程序总是在添加第一个实体时工作,而在添加第二个实体时总是崩溃。有时碰撞时不会出现错误,其他时候会出现不同类型的错误(有些错误包括在下面)。通过日志语句和跟踪,我看到程序在nsfetchResultsController的委托的ControllerWillChangeContent(调用[self.tableView beginUpdates])方法退出后崩溃,但在调用代码中的任何其他方法之前。 以下是我的代码的一些相关部分。配置nsfetchedresultsController:

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
    [fetchRequest setEntity:[NSEntityDescription entityForName:@"Beer"
                                        inManagedObjectContext:self.managedObjectContext]];
    
    // Configure request's entity and predicate
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
    NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
    [fetchRequest setSortDescriptors:sortDescriptors];
    [sortDescriptor release];
    [sortDescriptors release];
    
    NSString *expression = [NSString stringWithFormat:@"brewery.name LIKE \"%@\"", self.brewery.name];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:expression];
    [fetchRequest setPredicate:predicate];
    self.resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
                                                                 managedObjectContext:self.managedObjectContext
                                                                   sectionNameKeyPath:nil
                                                                            cacheName:nil];
    self.resultsController.delegate = self;
    [fetchRequest release];
    
    NSError *error = nil;
    BOOL success = [resultsController performFetch:&error];
    if (!success) {
        NSLog(@"Error fetching request %@", [error localizedDescription]);
    }
    

    添加新实体:

    NSEntityDescription *entity = [NSEntityDescription entityForName:@"Beer" inManagedObjectContext:self.managedObjectContext];
    Beer *beer = [[Beer alloc] initWithEntity:entity insertIntoManagedObjectContext:self.managedObjectContext];
    beer.name = beerName;
    beer.brewery = self.brewery;
    

    我已经在文档中看到了关于在一个部分中显示表时出现问题的警告,并且我使用了苹果的解决方法来解决这个问题。无论如何,这些方法在崩溃之前不会被调用。

    我收到的一些错误:

    Serious application error.  Exception was caught during Core Data change processing: *** -[NSCFString compareObject:toObject:]: unrecognized selector sent to instance 0x4e808c0 with userInfo (null)
    Serious application error.  Exception was caught during Core Data change processing: *** -[CALayer compareObject:toObject:]: unrecognized selector sent to instance 0x4e53b80 with userInfo (null)
    Serious application error.  Exception was caught during Core Data change processing: *** -[UITextTapRecognizer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4ca5d70 with userInfo (null)
    Serious application error.  Exception was caught during Core Data change processing: *** -[CALayer controllerWillChangeContent:]: unrecognized selector sent to instance 0x4e271a0 with userInfo (null)
    Serious application error.  Exception was caught during Core Data change processing: *** -[NSCFNumber countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance 0x4c96ee0 with userInfo (null)
    

    正如您所看到的,错误(出现错误时)是不一致的,即使没有对代码进行任何更改。

    有人知道我做错了什么吗?

    5 回复  |  直到 14 年前
        1
  •  4
  •   Marcus S. Zarra    15 年前

    您不一致的错误指出可能存在过度发布问题。尤其是更改代理以重新加载数据会使问题消失。就我个人而言,我会花时间来解决这个问题,而不是围绕它进行编码,因为您肯定在那里有一个代码问题,稍后可能会出现在其他地方。

    我将执行以下操作:

    1. 打开nszombie
    2. 为添加断点 objc_exception_throw
    3. 在调试器中运行

    当异常发生时,查看内存地址并查看访问的内容和位置。这将隔离问题并告诉您发生了什么。如果这不能揭示问题的话,发布你的 NSFetchedResultsController 委托方法,这样我就可以看到它们中是否有什么奇怪的地方。

    最好用附加信息更新原始问题。

        2
  •  1
  •   Stefan Arentz    15 年前

    创建新实体的代码都很奇怪。改为使用这个怎么样:

    Beer* beer = [NSEntityDescription insertNewObjectForEntityForName: @"Beer" 
        inManagedObjectContext: self.managedObjectContext];
    beer.name = @"Grolsch";
    

    另外,你没有打电话 NSManagedObjectContext#save: . 但也许你在你的代码中做了你现在所展示的部分?

        3
  •  1
  •   Drew C    15 年前

    虽然我没有解决这个特定的问题,但是我采用了一种稍微不同的方法来编写类,它提供了我想要的功能,并且没有导致问题出现。我仍在使用nsfetchedResultsController,但我只实现ControllerDidChangeContent:,而不是实现所有四个委托方法,它只调用[TableView ReloadData]。

    如果在Xcode中创建一个新的基于导航的应用程序,并使用核心数据进行存储,那么这是rootviewcontroller类中包含的实现。您可能会对表格编辑动画失去一些控制,但 许多的 更简单,对我来说很好。

        4
  •  1
  •   Brad Shuttleworth    14 年前

    我最近有一个类似的错误-你的问题是过度发布,特别是:

    [sortDescriptors release];
    

    从中获取SortDescriptors对象

    [NSArray arrayWithObjects:sortDescriptor, nil];
    

    它没有“alloc”、“copy”或“new”,因此它返回一个自动释放的对象。因为您很早就发布了它,所以有两个地方可以崩溃——当nsfetchrequest使用它时,以及当它被池释放时。见苹果公司 memory management guide 了解更多详细信息。

        5
  •  0
  •   Rog    14 年前

    这是一个旧的问题,但是为了让其他有相同问题的人受益,我花了几个小时的时间试图了解发生了什么,最后发现了导致这些随机崩溃的排序描述符的问题。

    错误消息各不相同,但主要与以下CompareObject:ToObject选择器相关。

    - nscfset compareObject:toObject::发送到实例的选择器无法识别 - _ nscfstring compareObject:toObject:]发送到实例的选择器无法识别

    我的建议是尝试从代码中删除所有排序描述符和谓词,然后逐个添加它们以找出问题所在。

    祝你好运! 罗格