3. チュートリアル1 : TODOアプリの実装

ここではチュートリアル1の実装について解説します。

3.1. NEC BaaS iOS SDK の追加

NEC BaaS iOS SDK を利用するためには、アプリケーションに SDK を組み込む必要があります。

SDK を追加するには、以下の手順を行います。

まず CocoaPods が必要になります。 CocoaPods を参照してインストールを行ってください。

次に、プロジェクトディレクトリに Podfile を追加します。

$ cd your-project directory
$ pod init

Podfile を編集し、NEC BaaS iOS SDK のポッドを追加します。

pod 'NecBaas', '~> 7.5.0'

ポッドをインストールします。

$ cd your-project directory
$ pod install

これでプロジェクトへの導入は完了です。 以後 .xcworkspace ファイルを開いてプロジェクトをビルド・実行できます。

3.2. ヘッダファイルの import

iOS SDK を使用するソースファイルは、適宜 Nebula.h ファイルを import する必要があります。

#import <NecBaas/Nebula.h>

3.3. AppDelegate クラス

AppDelegate クラスの application:didFinishLaunchingWithOptions: メソッド内で、 iOS SDK の初期化処理を行います。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Nebula 初期化処理
    [NBCore setUpWithAppId:APP_ID appKey:APP_KEY tenantId:TENANT_ID];
    [NBCore setEndPointUri:ENDPOINT_URI];

    return YES;
}

SDK の初期化には NBCore クラスを使用します。 setupWithAppId:appKey:tenantId: を使用して以下のパラメータを設定します。

  • テナントID
  • アプリケーションID
  • アプリケーションキー

また、setEndPointUri: を使用して、エンドポイントURIを設定します。

3.4. TodoListViewController クラス

アプリケーション本体は TodoListViewController クラスに実装します。 本クラスは UITableViewController を継承しており、Todo を Table View で表示します。

3.4.1. 初期化 (viewDidLoad)

- (void)viewDidLoad {
    [super viewDidLoad];

    [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"TodoCell"];

    self.todos = @[]; // initial
    [self reloadTodos:nil];
}

初期化は viewDidLoad で行います。

ここでは reloadTodos: を呼び出し、Todo 一覧の取得を開始しています。

3.4.2. Todo 一覧の取得

// Todo 一覧を取得する
- (IBAction)reloadTodos:(id)sender {
    // バケット取得
    NBObjectBucket *bucket = [[NBObjectBucket alloc] initWithBucketName:BUCKET_NAME];

    // クエリ生成
    NBQuery *query = [NBQuery new];
    [query setSortOrderWithKey:@"updatedAt" isAscend:YES];

    // クエリ実行
    [bucket queryInBackgroundWithQuery:query block:^(NSArray *objects, NSUInteger count, NSError *error) {
        if (!error) {
            self.todos = objects;
            [self.tableView reloadData];
        } else {
            NSLog(@"query error: %@", error);
        }
    }];
}

reloadTodos: で、サーバから Todo データの一覧を取得します。

最初にオブジェクトバケットのインスタンスを取得します。オブジェクトバケットは NBObjectBucket クラスの インスタンスとして作成し、initWithBucketName: でバケット名をセットします。

Todo データは、NBObjectBucket に対して queryInBackgroundWithQuery:block: を呼び出すことで取得できます。 クエリ(取得条件)は NBQuery クラスのインスタンスとして作成します。 ここでは更新日時(updatedAt)フィールド昇順で、全件取得するというクエリを作成しています。

処理が完了すると、block: 引数に指定したブロックが呼び出されます。 正常時は objects にオブジェクトの一覧が、error に nil が格納されます。 ここでは todos プロパティに objects を保存し、tableView の reloadData を呼び出して画面描画を行います。

3.4.3. 画面描画

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [self.todos count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TodoCell"];

    NBObject *todo = (self.todos)[indexPath.row];

    cell.textLabel.text = [todo objectForKey:@"description"];
    return cell;
}

UITableView の描画は UITableViewDelegate の対応するメソッドで行います。

サーバから取得した Todo データは todos プロパティに格納されています。 tableView:numberOfRowsInSection: は、todos に格納されているオブジェクト数をテーブルの行数として返します。

tableView:cellForRowAtIndexPath: で、具体的な TableView の cell を返却します。 todos の indexPath.row 番目の要素を取り出し、"description" キーに格納された文字列を cell のテキストとして 設定して返却します。

3.4.4. Todo の追加

画面右上の Add ボタンを押すと、Todo の追加処理に移ります。 この処理は Segue 経由で TodoEditViewController を起動することで行っています。

TodoEditViewController の Done ボタンを押すと TodoListViewController に戻りますが、 この際 todoText プロパティに設定されたテキストを保管します。

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    self.todoText = textView.text;
}

TodoListViewController は、上記テキストを取り出し、addTodo: を呼び出します。

- (IBAction)firstViewReturnActionForSegue:(UIStoryboardSegue *)segue
{
    if ([segue.identifier isEqualToString:@"done"]) {
        TodoEditViewController *vc = [segue sourceViewController];
        NSString *todo = vc.todoText;
        [self addTodo:todo];
    }
}

addTodo: では、Todo の追加処理を行います。

- (void)addTodo:(NSString *)description {
    // オブジェクト作成
    NBObject *todo = [NBObject objectWithBucketName:BUCKET_NAME];

   // オブジェクトに値を設定
    [todo setObject:description forKey:@"description"];

    // オブジェクト保存
    [todo saveInBackgroundWithBlock:^(NSArray *objects, NSUInteger count, NSError *error) {
        if (!error) {
            [self reloadTodos:nil];
        } else {
            NSLog(@"save error : %@", error);
        }
    }];
}

Todo データを NBObject クラスのインスタンスとして生成します。このとき、バケット名を指定します。

また、setObject:forKey: を呼び出して、description フィールドに Todo のテキストをセットします。

データの保存には saveInBackgroundWithBlock: メソッドを使用します。 このメソッドが呼び出されるとサーバにデータが送信され、処理が終了するとブロックが呼び出されます。 ここでは reloadTodos: を呼び出して画面更新処理を行います。

3.4.5. Todo の削除

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return YES; // 削除可能
}

// 削除処理
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    NBObject *obj = (self.todos)[indexPath.row];

    // オブジェクト削除
    [obj deleteInBackgroundWithBlock:^(NSError *error) {
        if (!error) {
            [self reloadTodos:nil];
        } else {
            NSLog(@"Delete failed: %@", error);
        }
    }];
}

Todo の削除処理は、tableView:commitEditingStyle:forRowAtIndexPath: で行います。 本処理は、Todo を左スワイプしたときに呼び出されます。

todos プロパティから、該当 NBObject インスタンスを取得し、 deleteInBackgroundWithBlock: を呼び出すとサーバに削除指示が送信されます。

削除が正常に完了するとブロックが呼び出されますので、画面をリロードします。