3

我正在使用 NSFetchedResultsController 和 NSFetchedResultsControllerDelegate 来驱动 UITableViewController/UITableView。单击按钮会通过 触发删除 NSManagedObject [managedObjectContext deleteObject:aManagedObject]

NSFetchedResultsControllerDelegate 方法正确触发,并且该行从 UITableView 中删除。

这就是事情变得奇怪的地方。当我调用[managedObjectContext save:&error]NSFetchedResultsControllerDelegate 方法controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:时,将使用已删除的 NSManagedObject 作为对象(并且 isDeleted 在托管对象上为 YES)并且更改类型为 NSFetchedResultsChangeInsert ,它将已删除的 NSManagedObject 添加回 UITableView。

我试图通过检查isDeleted委托方法中的标志来抑制插入,但这会导致beginUpdatesandendUpdates断言失败。

我做错了什么或不正常吗?我在某个地方错过了一步吗?

4

3 回答 3

0

你没有忘记下面的代码吗?

如果您仍然感到困惑,Apple 的示例代码,请参阅。会对你有很大帮助的。

iPhoneCoreData食谱

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    static NSString *cellIdentifier = @"cellIdentifier";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    }

    [self configureCell:cell atIndexPath:indexPath];

    return cell;
}

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
    // Configure the cell
    MyObject *recipe = (MyObject *)[fetchedResultsController objectAtIndexPath:indexPath];
    //do stuff
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
        UITableView *tableView = self.tableView;

        switch(type) {
            case NSFetchedResultsChangeInsert:
                break;

            case NSFetchedResultsChangeDelete:
                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;

            case NSFetchedResultsChangeUpdate:
                [self configureCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
                break;

            case NSFetchedResultsChangeMove:
                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                break;
        }
    }

- (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;
        }
    }
于 2012-08-10T23:55:03.553 回答
0

我暂时找到了解决方法:

[managedObjectContext deleteObject:managedObject];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    [managedObjectContext performBlock:^{
        resultsController.delegate = nil;
        [managedObjectContext save:nil];
        resultsController.delegate = self;
    }];
});

这会删除对象,让 NSFetchedResultsController 委托触发以从 UITableView 中删除行。然后稍后的调度会断开委托,执行保存然后重新附加委托。

于 2012-08-11T09:39:00.947 回答
0

面对与您完全相同的问题,我可以意识到,只有另一个对象或上下文对已删除对象的单个引用才能使其保持活动状态,直到删除引用为止。如果应用程序再次尝试访问已删除的对象,它将崩溃。单个引用可能是已删除对象重新出现的原因。

就我而言,在调用异步删除操作之前释放对将要删除的对象的 UIViewController 实例引用解决了这个问题。

// Delete a NSManagedObject.
NSManagedObjectID *objectID = [[managedObject objectID] copy];
// Release all references to the object.
self.managedObject = Nil;
// Asynchronously delete the object.
[self asynchronouslyDeleteManagedObjectWithManagedObjectID:objectID];

忽略该Release all references to the object部分会使对象重新出现,就像isDeleted在被删除到NSFetchedResultsController观察者实例后一样。

于 2012-10-15T12:42:14.677 回答