3

編集:最初の質問が間違っていたので、一部のコンテンツは少し無関係かもしれません。しかし、私が物事をしている方法のより良い印象をあなたに与えるかもしれません。

でかなり奇妙な問題が発生しましたNSFetchedResultsController。まず、アプリの現在の状況について説明します。抽象クラスのサブクラスである複数Albumのエンティティがあります。PhotoAbstractItem

私の場合、現在のすべての'を取得するためAlbumViewControllerに使用しています。このような:NSFetchedResultsControllerAbstractItemsuperAlbum

- (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:のタイプで呼び出されます。その人は現在に存在していません。そのため、コレクションビューで更新しようとすると失敗します。NSFetchedResultsChangeUpdateparentAlbumNSFetchedResultsController

現在にないオブジェクトが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
4

1 に答える 1

5

これが解決策なのか回避策なのかはわかりませんが、フェッチされた結果コントローラーを次の場所でリリースすると、次のようになりますviewWillDisappear

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

そうすれば、ErrorTestプログラムはもうクラッシュせず、正しく動作しているように見えます。

これにより、現在表示されていないコレクションビューの更新が回避されます。

あなたはすでにFRCにアクセスしているのでviewWillAppear

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

FRCのレイジーセッター機能により、ビューが再び表示されるようになると、FRCが再作成されます。

于 2012-10-06T16:25:53.440 に答える