ReactNativeでObjective-Cと連携してmBaaSを使う

# 概要

最近話題のReactjsベースでネイティブアプリを構築できるフレームワーク「React Native」
サーバー側と連携したいアプリを作りたい時に便利なのが「mobile backend as a Service(mbaas)」

今回は[ニフティクラウド mobile backend](http://mb.cloud.nifty.com/)をReact Nativeで使用する方法を試してみる

# 環境

使用した環境

* node.js
    * 5.0.0
* react-native
    * 0.1.7
* xcode
    * 7.2 

# プロジェクト作成

まずは以下のコマンドを実行してReact Nativeのプロジェクトを作成

```
$ react-native init {project_name}
```

# SDKをダウンロード

[ニフティクラウド mobile backend](http://mb.cloud.nifty.com/)はSDKとしてiOS用、Android用、Javascript用のSDKを提供している。
React NativeでiOSアプリを作る場合、iOS用とJavascript用どっちのSDKを使うべきか悩ましいところ。

React NativeはObjective-Cと簡単に連携できるので、今回は使い慣れているiOS用を使ってみる。

インストールはお馴染みのCocoaPodsで。

```:Podfile
target 'ncmb' do
    pod 'NCMB', :git => 'https://github.com/NIFTYCloud-mbaas/ncmb_ios.git'
end
```
```
$ pod install
```

# Objective-C側の実装

mobile backendのコントロールを実施するクラスを作成する。
プロジェクトディレクトリに以下の2ファイルを作成。

```objc:NCMBController.h
#import "RCTBridgeModule.h"

@interface NCMBController : NSObject <RCTBridgeModule>
@end
```
```objc:NCMBController.m
#import "NCMBController.h"
#import <NCMB/NCMB.h>

@implementation NCMBController

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(init:(RCTResponseSenderBlock)callback)
{
  // APPLICATION_KEYとCLIENT_KEYはダッシュボードから取得してね
  NSString *const APPLICATION_KEY = @"";
  NSString *const CLIENT_KEY      = @"";
  
  // mobile backendアプリとの連携
  [NCMB setApplicationKey:APPLICATION_KEY clientKey:CLIENT_KEY];
  callback(@[@"init ok"]);
}

RCT_EXPORT_METHOD(post:(NSString *)msg callback:(RCTResponseSenderBlock)callback)
{
  // TestClassへmessageを登録する
  NCMBObject *obj = [NCMBObject objectWithClassName:@"TestClass"];
  [obj setObject:msg forKey:@"message"];
  [obj saveInBackgroundWithBlock:^(NSError *error) {
    if (error){
      NSLog(@"[ERROR] %@", error);
    } else {
      callback(@[@"post ok"]);
    }
  }];
}

RCT_EXPORT_METHOD(fetch:(RCTResponseSenderBlock)callback)
{
  // TestClassからmessageを取得する
  NCMBQuery *query = [NCMBQuery queryWithClassName:@"TestClass"];
  [query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
    if (error){
      NSLog(@"[ERROR] %@", error);
    } else {
      NSString * resp = @"";
      for (NCMBObject * object in objects) {
        NSString * message = [object objectForKey:@"message"];
        resp = [resp stringByAppendingString: [@"\n" stringByAppendingString:message]];
      }
      callback(@[resp]);
    }
  }];
}
@end
```


## ポイント

* React NativeとObjective-Cの連携は、「RCTBridgeModule」プロトコルを実装したクラスを作成することで実現できる。

* mobile backendを操作するために、RCT_EXPORT_MODULEで「init」「post」「fetch」3つのメソッドをreact側から呼べるようにしておく。

# React側の実装

index.ios.jsを以下のように修正

```js:index.ios.js
'use strict';

var React = require('react-native');
var {
  AppRegistry,
  Text,
  View,
  TextInput,
  StyleSheet,
} = React;
// Objective-Cモジュールの読み込み
var NCMBController = require('NativeModules'). NCMBController;

var ncmb = React.createClass({
  getInitialState() {
    // init
    NCMBController.init((resp) => {});
    return{message:"", postData:""};
  },
  componentDidMount() {
    this.fetchData();
  },
  render: function() {
    return(
      <View style={styles.container}>
        <TextInput
          style={styles.input}
          onChangeText={(text) => this.setState({postData: text})}
          onBlur={(event) => this.submit(event)} />
        <Text>
          {this.state.message}
        </Text>
      </View>
    )
  },
  fetchData: function() {
    // データ取得
    NCMBController.fetch((resp)=> {
      this.setState({message:resp});
    });
  },
  submit: function(event) {
    var message = this.state.postData;
    // データ登録
    NCMBController.post(message, (resp) => {
      this.fetchData();
    });
  },
});


var styles = StyleSheet.create({
  container: {
    flex: 1,
    paddingTop: 40,
    backgroundColor: '#F5FCFF',
  },
  input: {
    height: 40,
    borderWidth: 1,
    borderColor: 'gray',
    padding: 10,
    margin: 10,
    fontSize: 15,
  },
});
AppRegistry.registerComponent('ncmb', () => ncmb);
```

## ポイント

* NativeModuleを使うことでObjective-Cのメソッドを呼べる
* submit()メソッドにてテキストボックスに入力した値をmBaaSに保存
* fetchData()メソッドでmBaaSから値を取得

取得したデータは通常のReactのお作法と同じでsetStateすることで、Viewに表示させる

### 画面

<img width="320" alt="Simulator Screen Shot 2015.12.22 0.16.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/63169/521d0495-0468-aeaa-e15d-ae2fc0fec13c.png">


# まとめ

Objective-Cを通すことで、React NativeからmBaaSへのデータ保存、取得が簡単にできた。
しかしObjective-Cを結構書かないといけないのが辛いところ。
次回は全部Javascript上で実装してみたい。

以上、NIFTY Cloud Advent Calendar 2015