编辑:最初的问题是错误的,所以有些内容可能有点不相关。但可能会让您对我做事的方式有更好的印象。
NSFetchedResultsController
我遇到了一个很奇怪的问题。首先,我将描述我的应用程序的当前情况。我有多个 Album
和 Photo
实体,它们都是抽象类 AbstractItem
的子类。
在我的 AlbumViewController
中,我使用 NSFetchedResultsController
获取所有 AbstractItem
与当前 superAlbum
。像这样:
- (NSFetchedResultsController *)fetchedResultsController {
if (!fetchedResultsController ) {
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"AbstractItem"
inManagedObjectContext:managedObjectContext]];
[request setSortDescriptors:@[
[NSSortDescriptor sortDescriptorWithKey:@"type" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:YES]
]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"superAlbum = %@", self.parentAlbum];
[request setPredicate:predicate];
NSFetchedResultsController *newController = [[NSFetchedResultsController alloc] initWithFetchRequest:request
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"type"
cacheName:nil];
newController.delegate = self;
self.fetchedResultsController = newController;
}
return fetchedResultsController;
}
当我选择一个 Album
时,另一个 AlbumViewController
实例被启动并推送到我的导航 Controller 上。在这种情况下,parentAlbum
被设置为所选对象。
现在,当我使用以下代码添加新的Album
时,会发生错误。
Album *album = (Album *)[Album itemInManagedObjectContext:self.managedObjectContext];
album.name = @"Test album";
album.superAlbum = self.parentAlbum;
NSError *error;
BOOL success = [self.managedObjectContext save:&error];
if (!success) {
NSLog(@"Error: %@", error);
}
方法 controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
被 parentAlbum
对象的类型 NSFetchedResultsChangeUpdate
调用.当前的 NSFetchedResultsController
中不存在那个。所以当它试图在 Collection View 中更新它时失败了。
不在当前 NSFetchedResultsController
中的对象怎么可能用于通知?我该如何解决这个问题?
编辑:
发布问题后,我意识到实际上不是 NSFetchedResultsController
通知了错误的对象。但它会通知前一个(父) Collection View 中的对象,但它会通知它自己的 Collection View Controller 。
但这可能就是问题所在; Collection View Controller 在不可见时收到通知,看起来目前无法处理。我这样处理通知:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeUpdate:
[self.collectionView reloadItemsAtIndexPaths:@[indexPath]];
break;
}
}
我很确定它之前运行良好。在迭代自上次提交以来所做的更改后,我让它再次工作。在我删除 UICollectionView
header (补充 View )后它再次工作。
因此:当我的 UICollectionView
有标题且当前不可见时,它无法更新项目。这是一个很难发现的问题,但如何解决?认为这是一个非常奇怪的问题。
我得到的错误:
2012-10-04 11:54:21.148 PhotoLibrary[9195:c07] -[NSISObjectiveLinearExpression coefficientForVariable:]: unrecognized selector sent to instance 0x968bae0
2012-10-04 11:54:21.151 PhotoLibrary[9195:c07] CoreData: error: Serious application error. Exception was caught during Core Data change processing. This is usually a bug within an observer of NSManagedObjectContextObjectsDidChangeNotification. -[NSISObjectiveLinearExpression coefficientForVariable:]: unrecognized selector sent to instance 0x968bae0 with userInfo (null)
2012-10-04 11:54:21.156 PhotoLibrary[9195:c07] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSISObjectiveLinearExpression coefficientForVariable:]: unrecognized selector sent to instance 0x968bae0'
*** First throw call stack:
(0x2977012 0x1418e7e 0x2a024bd 0x2966bbc 0x296694e 0xcb06c3 0xcb569c 0xcbf88e 0x58c670 0x5945bd 0x29198fd 0x594605 0x29198fd 0x594605 0x29198fd 0x594605 0x5946c7 0x9cd53 0x5525ff 0x9ea5c 0x5522f7 0x565228 0x56231b 0x55ed4e 0x55edf0 0x8f56 0x1242c1a 0xbcddc9 0x29d10c5 0x292befa 0xb02482 0x11545f3 0x11ede5f 0x114fa26 0x115316e 0x55dc 0x85e5 0x4312c1 0x142c705 0x57920 0x578b8 0x118671 0x118bcf 0x117d38 0x8733f 0x87552 0x653aa 0x56cf8 0x20badf9 0x20baad0 0x28ecbf5 0x28ec962 0x291dbb6 0x291cf44 0x291ce1b 0x20b97e3 0x20b9668 0x5465c 0x26bd 0x25e5)
libc++abi.dylib: terminate called throwing an exception
最佳答案
我不知道这是解决方案还是变通方法,但是如果您在 viewWillDisappear
中释放获取的结果 Controller :
- (void)viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
self.fetchedResultsController = nil;
}
那么您的 ErrorTest 程序就不会再崩溃,并且似乎可以正常工作。
这避免更新当前不可见的 Collection View 。
因为您已经在 viewWillAppear
中访问 FRC:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// ...
NSError *error = nil;
BOOL success = [self.fetchedResultsController performFetch:&error];
// ...
}
由于 FRC 的惰性设置函数,当 View 再次可见时将重新创建 FRC。
关于objective-c - UICollectionView 在包含标题时不会重新加载项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12718689/