NSFetchedResultsControllerを使ってTableViewを表示したい!
MagicalRecordもそれっぽく使えるようになって簡単にDB操作ができるようになったことだし、あらためてTableViewでデータを表示しようと思ってみた。
調べてみると、「NSFetchedResultsController」っていうのを使うといいらしい という情報を得た。どうにかこうにか表示までこぎ着けたのでメモ。
NSFetchedResultsControllerを使うと、どういいのか?
これを使うと、紐づけられたデータが更新された際に、表示を更新させたりするのが楽になるっぽげ。使っとこ。
Delegateを設定する
TableViewControllerで使うとすると、この.mファイルにDelegateをつけときます。
@interface RecordTableViewController () <NSFetchedResultsControllerDelegate>
NSFetchedResultsController の 変数を用意
使いやすいように、同じくTableViewController.mにNSFetchedResultsControllerの変数を用意しておきます。これに表示するデータを入れます。
@property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
NSFetchedResultsControllerにデータを入れる
TableViewで表示したいデータを、用意しておいたfetchedResultsControllerという変数に入れます。このクラスの中で使いやすいように、その名も「fetchedResultsController」とすることが多いっぽげ。なお、ここでは覚えたてのMagicalRecordを使ってデータを取り出しています。(SSCatっていうのは、Entityに紐づいたクラスです)
- (NSFetchedResultsController*)fetchedResultsController
{if(_fetchedResultsController == nil){self.fetchedResultsController = [SSCat fetchAllSortedBy:@"name" ascending:NO withPredicate:nil groupBy:nil delegate:self];}return _fetchedResultsController;}
セルを描画するメソッドを用意する
NSFetchedResultsControllerは値を更新するのを監視して、変更があると再描画することが出来ます。そんなこんなで何カ所かセルの描画をするタイミングがあるため、メソッドとして分けておきます。(ベタに書くならナシでもOK。)
今回は、指定行(indexPath)のデータにある「name」というattitudeをラベルに表示しています。cellと指定行を渡してもらうので、もしもTableViewに独自のcellを使いたい時はここも合わせないといけません。
-(void)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath
{
SSCat *cat = [_fetchedResultsController objectAtIndexPath:indexPath];cell.textLabel.text = cat.name;}
デリゲート用のメソッドを書く
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)typenewIndexPath:(NSIndexPath *)newIndexPath {UITableView *tableView = self.tableView;switch(type) {case NSFetchedResultsChangeInsert:[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];break;case NSFetchedResultsChangeDelete:[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationFade];break;case NSFetchedResultsChangeUpdate:[self configureCell:[tableView cellForRowAtIndexPath:indexPath]atIndexPath:indexPath];break;case NSFetchedResultsChangeMove:[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]withRowAnimation:UITableViewRowAnimationFade];[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade];break;}}
続いてdidChangeSectionの。こちらは挿入と削除に対応。
- (void)controller:(NSFetchedResultsController*)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch(type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
最後はcontrollerWillChangeContentとcontrollerDidChangeContent。特に何もなければTableViewに対してそれぞれのイベントを伝えてあげるだけで良いみたい。
- (void)controllerWillChangeContent:(NSFetchedResultsController*)controller
{
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController*)controller{
[self.tableView endUpdates];
}
通常該当の行の内容を返すメソッドを書き換え
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"];}[self configureCell:cell atIndexPath:indexPath];return cell;}
レベルアップ という言葉に惹かれてる。
レベルアップ Objective-C (Software Design plus)
- 作者: 沼田哲史
- 出版社/メーカー: 技術評論社
- 発売日: 2013/11/12
- メディア: 大型本
- この商品を含むブログを見る