Cocos2d-xでParse.comにログイン

Parse.comはモバイルアプリにバックエンドを提供するBaaSの一つで、ログインやデータの保存などサーバーサイドでの処理が必要な機能を簡単に追加することができます。

これをCocos2d-xから使ってみます。サンプルプロジェクトは以下になります。
[ntotani/cocos2dx-parsecom](https://github.com/ntotani/cocos2dx-parsecom)

Parse.comではiOS, Android用のSDKがそれぞれ提供されているので、Cocos2d-xではPlugin-Xからこれを利用します。Plugin-X自体の導入は[別記事](http://qiita.com/blankblank/items/0daf178e5e070a723798)にあります。まずは設定とログインを書きます。

```objc:UserParse.m
- (void) configDeveloperInfo : (NSMutableDictionary*) cpInfo
{
    [Parse setApplicationId:[cpInfo objectForKey:@"ApplicationID"]
                  clientKey:[cpInfo objectForKey:@"ClientKey"]];
    [PFTwitterUtils initializeWithConsumerKey:[cpInfo objectForKey:@"TwitterConsumerKey"] consumerSecret:[cpInfo objectForKey:@"TwitterConsumerSecret"]];
}
```
`setApplicationId`でParse.comのIDとKeyを設定します。また、今回はTwitterでログインできるようにもしたいので、TwitterのアプリIDも設定します。

```objc:UserParse.m
- (void) login
{
    PFLogInViewController* vc = [[PFLogInViewController alloc] init];
    vc.fields = PFLogInFieldsDefault | PFLogInFieldsTwitter;
    vc.delegate = self;
    [[AdsWrapper getCurrentRootViewController] presentViewController:vc animated:YES completion:nil];
}
```
`PFLogInViewController`はParse.com標準のログイン画面です。`fields`で表示させる要素を設定できます。また、プラグインの中からはRootViewControllerを直接参照できないので、`AdsWrapper`のヘルパーメソッドを使います。

ログイン処理ができたので、これを呼び出します。

```cpp:AppDelegate.cpp
    auto parse = dynamic_cast<ProtocolUser*>(PluginManager::getInstance()->loadPlugin("UserParse"));
    parse->setDebugMode(true);
    TUserDeveloperInfo devInfo;
    devInfo["ApplicationID"] = "your_app_id";
    devInfo["ClientKey"] = "your_client_key";
    devInfo["TwitterConsumerKey"] = "your_consumer_key";
    devInfo["TwitterConsumerSecret"] = "your_consumer_secret";
    parse->configDeveloperInfo(devInfo);
    parse->setActionListener(&s_parseListener);
```
```cpp:Runtime.cpp
    //startScript("");
    auto parse = dynamic_cast<ProtocolUser*>(PluginManager::getInstance()->loadPlugin("UserParse"));
    parse->login();
```
`applicationDidFinishLaunching`等でIDを設定し、`login`を呼びます。今回はサンプルということで、接続待ち画面のPLAYボタンをタップしたタイミングでログインしています。

ビルドして実行します。ハマりどころとして、Plugin-Xを使用するためリンカフラグに`-ObjC`を設定しますが、そのままだとParse.comのSDKがビルドできないのでFacebookSDKを追加してこれを回避します（[詳細](http://stackoverflow.com/questions/15457136/parse-for-ios-errors-when-trying-to-run-the-app)）。

![iOSシミュレータのスクリーンショット 2014.08.20 13.07.28.png](https://qiita-image-store.s3.amazonaws.com/0/2490/5b4632fb-60fc-ba5d-83b7-687983fe4fca.png)![iOSシミュレータのスクリーンショット 2014.08.20 13.07.31.png](https://qiita-image-store.s3.amazonaws.com/0/2490/2032e78c-54be-7215-1379-162038869dca.png)

ログイン画面が出れば成功です。ログインの結果は`PFLogInViewControllerDelegate`で受け取ることができるので、これを`UserActionListener`に流すとC++側で処理できます。

```objc:UserParse.m
- (void)logInViewController:(PFLogInViewController *)logInController didLogInUser:(PFUser *)user
{
    [UserWrapper onActionResult:self withRet:kLoginSucceed withMsg:user.username];
}

- (void)logInViewController:(PFLogInViewController *)logInController didFailToLogInWithError:(NSError *)error
{
    [UserWrapper onActionResult:self withRet:kLoginFailed withMsg:[error localizedDescription]];
}

- (void)logInViewControllerDidCancelLogIn:(PFLogInViewController *)logInController
{
    [UserWrapper onActionResult:self withRet:kLoginFailed withMsg:@"cancel"];
}
```
```cpp:AppDelegate.cpp
class ParseListener : public UserActionListener
{
    void onActionResult(ProtocolUser* pPlugin, UserActionResultCode code, const char* msg)
    {
        if (code == UserActionResultCode::kLoginSucceed) {
            log("parse login succeed: %s", msg);
        }
    }
};
static ParseListener s_parseListener;
```

## リンク
* [Parse](https://www.parse.com/)
* [[MBaaS] Parseで簡単モバイルバックエンド構築 – 【ざっと概要】](http://dev.classmethod.jp/cloud/parse-introduction-1/)
* [Parse for iOS: Errors when trying to run the app](http://stackoverflow.com/questions/15457136/parse-for-ios-errors-when-trying-to-run-the-app)