NSFetchedResultsController
テーブルビューのデータを更新するためにを使用しています。データ自体は、バックグラウンドで実行されるXMLパーサーを介して提供されます。パーサーが終了すると、データを独自のコンテキストに保存します。はNSFetchedResultsController
これらの変更をすぐに取得し、-(void)controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
更新された要素ごとにデリゲートメソッドの呼び出しを開始します。これも高速で、ログファイルでは完全に正常に見えます。
ただし、私は's-(void)controllerDidChangeContent:
と呼びます。次に、画面に更新アニメーションが表示されますが、すべてのセルで、半分しか表示されていない最後のセルのほかに、セルの左側にある画像だけが表示されます。すべてのテキストラベルが表示されるわけではありません。約5〜10秒かかり、その後すべてのラベルが表示されます。UITableView
-(void)endUpdates
ただし、のすべてのデリゲート呼び出しを無視して、すべてを呼び出すNSFetchedResultsController
だけで問題なく機能します。コンテンツはすぐにあります。[self.tableView reloadData]
-(void)controllerDidChangeContent:
私がここで間違っていることを誰かが知っていますか?プロファイラーは、メインスレッドが基本的に何もしていないことを示しています。テーブルビューにディスパッチされるイベントに加えて、タッチイベントは適切に処理されます。これらは処理されません。テーブルビューは真面目な仕事をしているようですが、アニメーションはすでに終わっているので、それが何であるかは本当にわかりません。
これが私の実装ですNSFetchedResultsControllerDelegate
:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"%s", __PRETTY_FUNCTION__);
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
NSLog(@"%s", __PRETTY_FUNCTION__);
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath*)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath*)newIndexPath {
NSLog(@"%s", __PRETTY_FUNCTION__);
UITableView* tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
case NSFetchedResultsChangeUpdate:
[(NewsItemCell*)[tableView cellForRowAtIndexPath:indexPath] updateWithNews:[self.fetchedResultsController objectAtIndexPath:indexPath]];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
NSLog(@"%s", __PRETTY_FUNCTION__);
[self.tableView endUpdates];
}
そして、これは私のセルレイアウトのコードです:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.fetchedResultsController.sections.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id<NSFetchedResultsSectionInfo> sectionInfo = [self.fetchedResultsController.sections objectAtIndex:section];
return sectionInfo.numberOfObjects;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
News* model = [self.fetchedResultsController objectAtIndexPath:indexPath];
NewsItemCell* cell = (NewsItemCell*)[tableView dequeueReusableCellWithIdentifier:NewsCellReuseIdentifier];
[cell updateWithNews:model];
cell.accessoryType = (model.content ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone);
return cell;
}
そして、セルのかなり基本的な更新:
- (void)updateWithNews:(News*)news {
NSString* dateString = [[NSDateFormatter outputDateFormatter] stringFromDate:news.date];
self.headlineLabel.text = (news.headline ? news.headline : NSLocalizedString(@"<NewsNoHeadlineReplacement>", nil));
self.metaInfoLabel.text = [NSString stringWithFormat:NSLocalizedString(@"<NewsMetaInfoFormatDate>", nil), (dateString ? dateString : (NSLocalizedString(@"<NewsNoDateReplacement>", nil)))];
self.readIndicatorView.hidden = (news.read != nil && [news.read compare:news.parsingDate] == NSOrderedDescending);
}
プレースホルダー文字列も表示されません。ラベルは完全に空です。画像のみが表示されます!