読者です 読者をやめる 読者になる 読者になる

まゆたまガジェット開発逆引き辞典

電子工作やプログラミングのHowtoを逆引き形式で掲載しています。作りたいモノを決めて学んでいくスタイル。プログラマではないので、コードの汚さはお許しを

■[iPhone開発記事]TabbarでCoreDataを使う(カスタムセルを使用)2

すいません、おそらくこっちの記事のほうが正確です。
この記事、TabbarでCoreDataを使う - ガジェット充まゆたまのiPhone開発とかいろいろ逆引きメモ SQLの名前を自分のプロジェクト名にしなければならない等、一部説明が飛んでいました。詳しい導入方法は以下のサンプルのReadMeをご覧ください。

長いのでポイントだけ。サンプルはこちらです。GitHub - prince9/TabCoreDataTempNew: (Sorry,Japanese only)CoreDataを使い、Tab1で入力したテキストをTab3のセルに書き込みます。TableViewContorollerを使わず、ViewContorollerにTableViewを設置してかつCoreDataを使うサンプルです

今回のポイントは以下になります。
・CoreDataを使い、Tab1で入力したテキストをTab3のTableViewに書き込む
・カスタムセルにCoreDataのデータを書き込む
・カスタムセルに書き込まれたデータを次のVIewで閲覧できるようにする(セルをクリックすると詳細を表示するViewに飛ぶ)

まず、CoreDataを使い、Tab1で入力したテキストをTab3のTableViewに書き込むことから。
これはTab1のTextFieldにテキストを入力してボタンを押すと、NotificationによってTab3の「- (void)insertNewObject」が呼び出されてTableViewに書き込まれます。
その際、注意点があります。それは「Tabbarはタブをタップしない限りViewが作られない」ということです。
ですので、擬似的にTab3をタップしてあげないといけません。が、前の記事にも書いた通りイマイチ上手くいかず、以下の力技を用いています。

- (void)viewWillAppear:(BOOL)animated {
    //セルのあるタブを選択したことにする
    UITabBarController *controller = self.tabBarController;
    controller.selectedViewController = [controller.viewControllers objectAtIndex: 2];
    //0.05秒後に1つ目のタブ(Tab1ViewController)に戻る
    [self performSelector:@selector(delayTab) withObject:nil afterDelay:0.05f];
    
    [super viewWillAppear:animated];
}
//1つ目のタブ(Tab1ViewController)に戻る
- (void)delayTab {
    
    UITabBarController *controller = self.tabBarController;
    controller.selectedViewController = [controller.viewControllers objectAtIndex: 0];
    
}

次、「カスタムセルにCoreDataのデータを書き込む」です。
これはそんなに複雑ではなく、UIViewrControllerにTableViewとTableView Cellを配置して結びつけるだけです。
が、ここも注意点があります。
Storyboardで結びつけをする場合、TableViewの中身のLabelやImageVIewは結びつけてはいけません。エラーが出ます。TableViewを結びつけて、LabelやImageViewの「Tag」をStoryboardとコードそれぞれに設定します。

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
    //現在の行に表示するデータを取得
    NSManagedObject *managedObject = [self.fetchedResultsController objectAtIndexPath:indexPath];
    
    //日時を日本時間に変換
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"yyyy年 MM/dd HH:mm"];
    
    NSString *dateString = [formatter stringFromDate:[managedObject valueForKey:@"timeStamp"]];
    
    //上からデータを取り出してテキストに設定
    //storyboardでTableViewを設置した場合はLabelやImageViewをひも付けないこと
    //タグを設定することでどれがどれか識別できる。storyboardの「Tag」で設定してから以下に入力する

    dateText = (UILabel*)[cell viewWithTag:1];
    subText1 = (UILabel*)[cell viewWithTag:2];
    subText2 = (UILabel*)[cell viewWithTag:3];
    dateText.text = dateString;
    subText1.text = [managedObject valueForKey:@"addText"];
    subText2.text = [managedObject valueForKey:@"addText2"];

そして最後の「セルをクリックすると詳細を表示するViewに飛ぶ」です。これは前にCoreDataの記事を書いたときに書き忘れてしまったので、ここで補足しておきます。

・Tableが表示されているViewの.m

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"showDetail"]) {
        
        
        NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
        NSManagedObject *selectedObject = [[self fetchedResultsController] objectAtIndexPath:indexPath];
        DetailViewController *detailViewController = [segue destinationViewController];
        [detailViewController setDetailItem:selectedObject];
        
        //DetailViewControllerでセルの中身を表示できるよう準備する
        detailViewController.myStr = [selectedObject valueForKey:@"addText"];
        detailViewController.myStr3 = [selectedObject valueForKey:@"addText2"];
        
        //日時を日本時間に変更
        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setDateFormat:@"yyyy年 MM/dd HH:mm"];
        NSString *dateString2 = [formatter stringFromDate:[selectedObject valueForKey:@"timeStamp"]];
        detailViewController.myStr2 = dateString2;
        
    }
}

・セルのデータの詳細を表示するViewの.h

@interface DetailViewController : UIViewController {
    NSString *myStr;
    NSString *myStr2;
    NSString *myStr3;
}
...

・セルのデータの詳細を表示するViewの.m

- (void)viewDidLoad
{
    [super viewDidLoad];
	// Do any additional setup after loading the view.
    myLabel.text = myStr;
    detailDescriptionLabel.text = myStr2;
    myLabel2.text = myStr3;
}
...