iOSアプリ開発で一番使いかつ、使い方が厄介なのが私個人UITableViewだと思っています。
そこでいろいろなサイトやサンプルを解析し自分なりにたどり着いた使い回しが楽なUITableViewの使い方をご紹介します。もっと使い回しができる方法があったら教えてください。
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (strong, nonatomic) NSFetchedResultsController *fetchController;
@property (strong, nonatomic) NSPredicate *pred;
...
としておきます。
よく見かけるサンプル等はNSArray等を使用しUITableViewに表示するDataを格納しています。私はあえてArrayを使わずNSFetchedResultsControllerを使用します。理由は簡単で汎用性があるからです。Arrayのようにも使えるので便利です。
次に適当な場所。- (void)viewDidLoad等のなかで*fetchControllerを制御します。
例えばこんな感じです。
- (void)viewDidLoad{
_fetchController = [Item fetchAllSortedBy:@"price"
ascending:YES
withPredicate:_pred
groupBy:nil
delegate:self];
...
}
predに関しては別のところで適宜宣言してください。Itemは別で準備したEntityです。例えばこのように宣言しているとします。xcodeの機能で自動生成したものです。
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Item : NSManagedObject
@property (nonatomic, retain) NSString * category;
@property (nonatomic, retain) NSString * regdate;
@property (nonatomic, retain) NSString * idstring;
@property (nonatomic, retain) NSString * nickname;
@property (nonatomic, retain) NSData * qrcode;
@property (nonatomic, retain) NSNumber * stockstate;
@property (nonatomic, retain) NSData * photo;
@property (nonatomic, retain) NSNumber * price;
@end
NSFetchedResultsControllerのdelegateをselfにしているので以下を貼付けておきます。ほぼお決まりのパターンなのでここまでは完全にコピーで使い回し可能です。
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller{
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(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 NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
[self.tableView endUpdates];
}
別の作業でItemが追加や削除されると即座に_fetchControllerが更新されるので便利です。つぎにUITableViewを実装します。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [_fetchController.fetchedObjects count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
ItemTableCell * cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
Item *item = [_fetchController objectAtIndexPath:indexPath];
[cell configureCellView:item];
return cell;
}
いつも通りですね。特徴なのは、[_fetchController.fetchedObjects count]で中身のObject数をカウントしているのと、[_fetchController objectAtIndexPath:indexPath]で選択されたobjectを指定している点です。
私はこの使い方に行き着きました。