包含标头时,UICollectionView不会重新加载项目

时间:2012-10-04 00:15:05

标签: objective-c cocoa-touch core-data ios6 uicollectionview

编辑:最初的问题是错误的,因此有些内容可能有点无关。但是可能会让你对我正在做的事情有更好的印象。

NSFetchedResultsController我遇到了一个非常奇怪的问题。首先,我将描述我的应用程序的当前情况。我有多个AlbumPhoto个实体,它们都是抽象类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实例并将其推送到我的导航控制器上。在这种情况下,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:对象的类型NSFetchedResultsChangeUpdate调用方法parentAlbum。当前的NSFetchedResultsController中没有那个。因此,当它尝试在集合视图中更新它时失败。

如何将不在当前NSFetchedResultsController中的对象用于通知?我该如何解决这个问题?

修改
在发布问题之后,我意识到实际上并不是NSFetchedResultsController通知错误的对象。但是它会通知前一个(父)集合视图中的对象,但它会对它自己的集合视图控制器执行此操作。

但这可能只是问题;集合视图控制器在不可见时收到通知,此时看起来无法处理。我像这样处理通知:

- (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标题(补充视图)后,它再次起作用。

所以:我的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

1 个答案:

答案 0 :(得分:5)

我不知道这是解决方案还是解决方法,但是如果您在viewWillDisappear中释放获取的结果控制器:

- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    self.fetchedResultsController = nil;
}

然后你的ErrorTest程序不再崩溃,似乎工作正常。

这可以避免更新当前不可见的集合视图。

由于您已经在viewWillAppear中访问了FRC:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // ...    
    NSError *error = nil;
    BOOL success = [self.fetchedResultsController performFetch:&error];
    // ...
}

由于FRC的懒惰设置功能,当视图再次可见时,FRC将重新创建。