我有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:当我导入新照片时也会发生这种情况,这些照片也会改变宣传照片。