【问题标题】:Is it possible to have an NSFetchedResultsController delete an object if one of the object's properties doesn't fulfil it's predicate?如果对象的属性之一不满足它的谓词,是否可以让 NSFetchedResultsController 删除对象?
【发布时间】:2013-10-08 14:00:25
【问题描述】:

我有一个由对象列表填充的NSFetchedResultsController-backed UICollectionViewController。每个对象都有一个称为已删除的 BOOL 属性。我的 fetch 控制器使用以下谓词来过滤我的对象。

[NSPredicate predicateWithFormat:@"deleted == NO"];

我的问题是,当我通过将对象标记为deleted = @YES 来删除它时。随后的didChangeObject: 方法告诉我该对象已更新并且 删除。并且该对象不会从集合视图中删除。如果我退出并重新加载我的应用程序,该对象不会显示在集合视图中,这是正确的行为。

我做错了什么,还是NSFetchedResultsController 的预期行为?

此处要求更新代码:

获取控制器配置:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"deleted == %@", @NO];
NSSortDescriptor *timestampSortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timestamp" ascending:NO];
NSSortDescriptor *prioritySortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"priority" ascending:NO];
NSManagedObjectContext *managedObjectContext = [NSManagedObjectContext MR_defaultContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:[GYNotification description] inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
[request setIncludesSubentities:YES];
[request setSortDescriptors:sortDescriptors];       
[request setPredicate:predicate];

NSFetchedResultsController *aFetchedResultsController =
    [[NSFetchedResultsController alloc] initWithFetchRequest:request
                                           managedObjectContext:managedObjectContext
                                             sectionNameKeyPath:sectionNameKeyPath
                                                      cacheName:nil];

然后是 fetch 控制器委托方法:

- (void)controller:(NSFetchedResultsController *)controller
   didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath
     forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath {
    NSMutableDictionary *change = [NSMutableDictionary new];
    switch(type) {
        case NSFetchedResultsChangeInsert:
            change[@(type)] = newIndexPath;
            break;
        case NSFetchedResultsChangeDelete:
            change[@(type)] = indexPath;
            break;
        case NSFetchedResultsChangeUpdate:
            change[@(type)] = indexPath;
            break;
        case NSFetchedResultsChangeMove:
            change[@(type)] = @[indexPath, newIndexPath];
            break;
    }
    [_objectChanges addObject:change];
}

- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    if ([_objectChanges count] > 0) {
        [self.collectionView performBatchUpdates:^{
            for (NSDictionary *change in _objectChanges) {
                [change enumerateKeysAndObjectsUsingBlock:^(NSNumber *key, id obj, BOOL *stop) {
                    NSFetchedResultsChangeType type = [key unsignedIntegerValue];
                    switch (type)
                    {
                        case NSFetchedResultsChangeInsert:
                            [self.collectionView insertItemsAtIndexPaths:@[obj]];
                            break;
                        case NSFetchedResultsChangeDelete:
                            [self.collectionView deleteItemsAtIndexPaths:@[obj]];
                            break;
                        case NSFetchedResultsChangeUpdate:
                            [self.collectionView reloadItemsAtIndexPaths:@[obj]];
                            break;
                        case NSFetchedResultsChangeMove:
                            [self.collectionView moveItemAtIndexPath:obj[0] toIndexPath:obj[1]];
                            break;
                    }
                }];
            }
        } completion:nil];
    }

    [_objectChanges removeAllObjects];
}

【问题讨论】:

  • 这看起来像是预期的行为,因为您实际上并没有删除对象,而是您创建的 update 属性,而 NSFetchedResultsController 对此一无所知。如果您使用 managedObjectContext 的 deleteObject: 方法,NSFetchedResultsController 会正确检测到对象删除,但它如何知道您的“已删除”属性?
  • 显示更多 FRC 配置和委托方法的代码。
  • NSFetchedResultsController updating with wrong update type 的可能重复项 - 答:您不能将您的属性称为“已删除”。

标签: ios objective-c core-data nsfetchedresultscontroller


【解决方案1】:

这种行为听起来像我对NSFetchedResultsController 的期望。您实际上只是对您的一个对象进行更新。事实上,它被命名为deleted 并没有什么区别。事实上,在我看来,称它为deleted 有点危险,因为NSManagedObject 已经有一个isDeleted 方法。

听起来您想隐藏某些托管对象而不是真正删除它们。我建议将 deleted 属性重命名为 shouldBeVisiblemarkedForDeletion。这样一来,意图就更清晰了,并且不会对您的对象真正处于什么状态感到困惑。

【讨论】:

  • 通过调用属性而不是删除的东西,解决了问题。非常感谢。
  • 遇到了完全相同的问题,甚至从未考虑过属性名称会导致问题。谢谢!
【解决方案2】:

您需要像这样删除您的托管对象:

NSManagedObjectContext *context = ... ;
NSManagedObject *managedObjectToDelete = ... ;

[context deleteObject:managedObjectToDelete];

只有这样您的NSFetchedResultsController 才会检测到删除。

【讨论】:

  • 我通常会删除它们,但在这种情况下,我需要保留它们。
猜你喜欢
  • 1970-01-01
  • 2015-08-25
  • 2011-04-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-02
  • 1970-01-01
相关资源
最近更新 更多