UICollectionView"崩溃"在CoreData中更新之后

时间:2016-11-18 12:41:35

标签: ios objective-c core-data uicollectionview nsfetchedresultscontroller

我有NSManagedObject 照片,其中包含以下属性:

promoted NSNumber(BOOL)
date NSDate
id NSNumber(Int32)

然后有一个UICollectionView,它应该显示所有的照片,并且有一个NSFetchedResultsController,并且是`NSFetchedResultsControllerDelegate'。 FRC具有上面提到的属性sortdescriptors(与上面相同的顺序)和提升为sectionKey。

所以CollectionView应如下所示: 第一部分仅显示全宽度的提升照片。 所有其他照片应显示在第二部分的网格中。

一切正常。

现在,推广的照片应该不时改变。

我基本上做的是:

  • 创建背景NSMangagedObjectContext
  • 获取所有照片
  • 浏览所有照片
    • 如果找到新的推广照片,则会将其标记为已提升
    • 任何其他标记为未提升
  • 完成后,保存背景上下文。

背景上下文现在与maincontext

合并

这一切都有效,但当`NSFetchedResultsControllerDelegate' -methods启动时,我收到以下错误:

2016-11-18 13:09:30.329[34954:1275641] *** Assertion failure in -[UICollectionView _endItemAnimationsWithInvalidationContext:tentativelyForReordering:animator:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.5.2/UICollectionView.m:5420
2016-11-18 13:09:30.331633 [34954:1275641] [error] error: Serious application error.  An exception was caught from the delegate of NSFetchedResultsController during a call to -controllerDidChangeContent:.  attempt to insert item 1 into section 0, but there are only 1 items in section 0 after the update with userInfo (null)

但是,在我发生所有变化之后,我保存起来并不知道为什么它似乎与第一部分中的大量项目相冲突。

我的NSFetchedResultsControllerDelegate - 方法如下:

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {

    _objectChanges = [NSMutableDictionary dictionary];
    _sectionChanges = [NSMutableDictionary dictionary];

}

- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
    if (type == NSFetchedResultsChangeInsert || type == NSFetchedResultsChangeDelete) {
        NSMutableIndexSet *changeSet = _sectionChanges[@(type)];
        if (changeSet != nil) {
            [changeSet addIndex:sectionIndex];
        } else {
            _sectionChanges[@(type)] = [[NSMutableIndexSet alloc] initWithIndex:sectionIndex];
        }
    }
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
       atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
      newIndexPath:(NSIndexPath *)newIndexPath
{
        NSMutableArray *changeSet = _objectChanges[@(type)];
        if (changeSet == nil) {
            changeSet = [[NSMutableArray alloc] init];
            _objectChanges[@(type)] = changeSet;
        }

        switch(type) {
            case NSFetchedResultsChangeInsert:
                [changeSet addObject:newIndexPath];
                break;
            case NSFetchedResultsChangeDelete:
                [changeSet addObject:indexPath];
                break;
            case NSFetchedResultsChangeUpdate:
                [changeSet addObject:indexPath];
                break;
            case NSFetchedResultsChangeMove:
                [changeSet addObject:@[indexPath, newIndexPath]];
                break;
        }
}



- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{

        NSMutableArray *moves = _objectChanges[@(NSFetchedResultsChangeMove)];
        if ([moves count] > 0) {
            NSMutableArray *updatedMoves = [[NSMutableArray alloc] initWithCapacity:[moves count]];

            NSMutableIndexSet *insertSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
            NSMutableIndexSet *deleteSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
            for (NSArray *move in moves) {
                NSIndexPath *oldIndexPath = move[0];
                NSIndexPath *newIndexPath = move[1];

                if ([deleteSections containsIndex:[oldIndexPath section]]) {
                    if (![insertSections containsIndex:[newIndexPath section]]) {
                        NSMutableArray *changeSet = _objectChanges[@(NSFetchedResultsChangeInsert)];
                        if (changeSet == nil) {
                            changeSet = [[NSMutableArray alloc] initWithObjects:newIndexPath, nil];
                            _objectChanges[@(NSFetchedResultsChangeInsert)] = changeSet;
                        } else {
                            [changeSet addObject:newIndexPath];
                        }
                    }
                } else if ([insertSections containsIndex:[newIndexPath section]]) {
                    NSMutableArray *changeSet = _objectChanges[@(NSFetchedResultsChangeDelete)];
                    if (changeSet == nil) {
                        changeSet = [[NSMutableArray alloc] initWithObjects:oldIndexPath, nil];
                        _objectChanges[@(NSFetchedResultsChangeDelete)] = changeSet;
                    } else {
                        [changeSet addObject:oldIndexPath];
                    }
                } else {
                    [updatedMoves addObject:move];
                }
            }

            if ([updatedMoves count] > 0) {
                _objectChanges[@(NSFetchedResultsChangeMove)] = updatedMoves;
            } else {
                [_objectChanges removeObjectForKey:@(NSFetchedResultsChangeMove)];
            }
        }

        NSMutableArray *deletes = _objectChanges[@(NSFetchedResultsChangeDelete)];
        if ([deletes count] > 0) {
            NSMutableIndexSet *deletedSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
            [deletes filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSIndexPath *evaluatedObject, NSDictionary *bindings) {
                return ![deletedSections containsIndex:evaluatedObject.section];
            }]];
        }

        NSMutableArray *inserts = _objectChanges[@(NSFetchedResultsChangeInsert)];
        if ([inserts count] > 0) {
            NSMutableIndexSet *insertedSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
            [inserts filterUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(NSIndexPath *evaluatedObject, NSDictionary *bindings) {
                return ![insertedSections containsIndex:evaluatedObject.section];
            }]];
        }

        UICollectionView *collectionView = [self collectionView];

        [collectionView performBatchUpdates:^{
            NSIndexSet *deletedSections = _sectionChanges[@(NSFetchedResultsChangeDelete)];
            if ([deletedSections count] > 0) {
                [collectionView deleteSections:deletedSections];
            }

            NSIndexSet *insertedSections = _sectionChanges[@(NSFetchedResultsChangeInsert)];
            if ([insertedSections count] > 0) {
                [collectionView insertSections:insertedSections];
            }

            NSArray *deletedItems = _objectChanges[@(NSFetchedResultsChangeDelete)];
            if ([deletedItems count] > 0) {
                [collectionView deleteItemsAtIndexPaths:deletedItems];
            }

            NSArray *insertedItems = _objectChanges[@(NSFetchedResultsChangeInsert)];
            if ([insertedItems count] > 0) {
                [collectionView insertItemsAtIndexPaths:insertedItems];
            }

            NSArray *reloadItems = _objectChanges[@(NSFetchedResultsChangeUpdate)];
            if ([reloadItems count] > 0) {
                [collectionView reloadItemsAtIndexPaths:reloadItems];
            }

            NSArray *moveItems = _objectChanges[@(NSFetchedResultsChangeMove)];
            for (NSArray *paths in moveItems) {
                [collectionView moveItemAtIndexPath:paths[0] toIndexPath:paths[1]];
            }
        } completion:^(BOOL finished) {
                _objectChanges = nil;
                _sectionChanges = nil;

        }];
}

BTW:当我导入新照片时也会发生这种情况,这些照片也会改变宣传照片。

0 个答案:

没有答案