個人で開発しているアプリ、keyaki2のバックエンドをparse.comからNIFTY Cloudへ移行した話です。
keyaki2は欅坂46のブログリーダーです。メンバーごとに新着ブログの通知をプッシュで送ってくれます。
ついでにCocoaPodsの導入、Gitの導入と、開発と本番で叩くAPIを変えるように実装したいと思っています。
クソプロジェクトを保守しやすいマシなものにしよう(メインはmBaaSの切り替え)
っていう大きなテーマを掲げていきたいと思います。
以降、NIFTY Cloud Mobile BackendをNCMBと称します。
現在の状態
【Parse版 keyaki2】
CocoaPods未導入。手作業の温かみでライブラリを追加していました。
具体的な移行手順
いきなりParse版からNCMB版に切り替えてしまうと、いろいろ大変なことが起きそうなので
移行期間を作ってゆっくり移行していきたいと思います。
1. Parse版にNCMBのSDKをインストール
こちらも手作業の温かみが良さそうなのでGitHubからSDKを落としてきて入れようとしたのですが、
なぜかうまく行かなかったので、結局CocoaPodsをこちらにも導入することにしました。
ターミナル上で.xcodeproj
があるディレクトリに移動して
$ pod init
生成されたPodfileに
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
target 'keyaki2' do
# Comment this line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for keyaki2
pod 'NCMB', :git => 'https://github.com/NIFTYCloud-mbaas/ncmb_ios.git'
end
pod NCMB...
を追記して保存します。
$ pod install
を実行してCocoaPodsのプロジェクトを作成します。
生成された.xcworkspace
をXcodeで開いてビルドが通ればとりあえずOKです。
2. DeviceTokenの設定を行う
必要とする場所に #import <NCMB/NCMB.h>
を記述してください。
僕の場合はPrefixHeader.h
にライブラリ関係を入れているので、そこに記述しました。(楽ちん
まずはDeviceTokenをParseにも、NCMBにも登録するためにAppDelegate.m
にいろいろ書いていきます。
アプリのキーや設定関係をコードに直接書くのがイヤなので、僕はConst.hというファイルに定数を置いてます。
Parseの設定ができているのであれば、一行追加するだけでOKです。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Parseの初期化
[Parse setApplicationId:K2ParseAppId clientKey:K2ParseClientKey];
//NCMBの設定を行う
[NCMB setApplicationKey:K2NiftyAppId clientKey:K2NiftyClientKey];
//通知の設定(デバイストークンの取得などを行う)
UIUserNotificationType userNotificationTypes = (UIUserNotificationTypeAlert |
UIUserNotificationTypeBadge |
UIUserNotificationTypeSound);
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:userNotificationTypes
categories:nil];
[application registerUserNotificationSettings:settings];
[application registerForRemoteNotifications];
//略
}
//Parse関連
static NSString *const K2ParseAppId = @"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
static NSString *const K2ParseClientKey = @"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
//Parse関連
static NSString *const K2NiftyAppId = @"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
static NSString *const K2NiftyClientKey = @"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
次に、DeviceTokenが返ってきた時にNiftyにも送るようにコードを書いていきます。
同じくAppDelegate.m
に記述していきます。基本的には追記していくだけです。
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
//Parse版で元々記述されていた処理
PFInstallation *currentInstallation = [PFInstallation currentInstallation];
[currentInstallation setDeviceTokenFromData:deviceToken];
[currentInstallation saveInBackground];
//以下を追記
//端末情報を扱うNCMBInstallationのインスタンスを作成
NCMBInstallation *installation = [NCMBInstallation currentInstallation];
//Device Tokenを設定
[installation setDeviceTokenFromData:deviceToken];
//端末情報をデータストアに登録
[installation saveInBackgroundWithBlock:^(NSError *error) {
if(!error){
//端末情報の登録が成功した場合の処理
} else {
//端末情報の登録が失敗した場合の処理
if (error.code == 409001){
//失敗した原因がdeviceTokenの重複だった場合
[self updateExistInstallation:installation];
} else if (error.code == 404001) {
//deviceTokenの重複以外のエラーが返ってきた場合
[self reRegistInstallation:installation];
}
}
}];
}
//deviceTokenの重複で端末情報の登録に失敗した場合に上書き処理を行う
- (void)updateExistInstallation:(NCMBInstallation*)currentInstallation{
NCMBQuery *installationQuery = [NCMBInstallation query];
[installationQuery whereKey:@"deviceToken" equalTo:currentInstallation.deviceToken];
NSError *searchErr = nil;
NCMBInstallation *searchDevice = [installationQuery getFirstObject:&searchErr];
if (!searchErr){
//上書き保存する
currentInstallation.objectId = searchDevice.objectId;
[currentInstallation saveInBackgroundWithBlock:^(NSError *error) {
if (!error){
//端末情報更新に成功したときの処理
} else {
//端末情報更新に失敗したときの処理
}
}];
} else {
//端末情報の検索に失敗した場合の処理
}
}
- (void) reRegistInstallation:(NCMBInstallation *) installation {
installation.objectId = nil;
[installation saveInBackgroundWithBlock:^(NSError *error){
if (!error) {
NSLog(@"NCMB installation : successfully re-regist.");
} else {
NSLog(@"NCMB installation : failed to re-regist. %@",error);
}
}];
}
これでDeviceTokenがParseとNiftyの両方に向くようになりました。
基本的な移行版の作成はこれだけでいいのですが、keyaki2ではメンバーごとにブログの通知を送るため、
ユーザはそれぞれチャンネルに登録を行っています。今回はその設定もNiftyに移行したいため、
こちらのコードも書いていきます。
3.Channelsの設定をNiftyへ移行する
通知チャンネルの移行は、「Parseで登録しているチャンネルリストをNiftyにも送る」という方法で
いきたいと思います。
以下に移行するためのメソッドを示します。僕はどこからでも呼べるようにUtilsクラス内に入れました。
+(void)syncNotificationSettings;
+(void)syncNotificationSettings{
NSArray *subscribedChannels = [PFInstallation currentInstallation].channels;
NCMBInstallation *installation = [NCMBInstallation currentInstallation];
[installation setObject:subscribedChannels forKey:@"channels"];
//端末情報をデータストアに保存
[installation saveInBackgroundWithBlock:^(NSError *error) {
NSLog(@"installationIdInBlock:%@", installation.objectId);
if(!error){
//端末情報の登録が成功した場合の処理
NSLog(@"Sync successful!");
} else {
//端末情報の登録が失敗した場合の処理
NSLog(@"Sync failed...");
}
}];
}
とりあえずこれ呼んでおけば同期できるっぽいのでいいのかな…と思ってたりします。
パフォーマンス的にどうかとは思いますが(未検証)、とりあえずAppDelegate内でそういう処理を書いちゃえば
とりあえず移行はできるだろうということで…。
再びAppDelegate.m
に戻って
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
//どこか適当な位置に(return直前とかいいかもしれない)
[Utils syncNotificationSettings];
return;
}
って置いておけばコールドスタート時にはとりあえず設定は同期できるはずです。
あとはユーザがchannelの設定を変更した時にもこのメソッドを呼べば完璧ですね。
一旦この状態でアプリをビルド、リリースしてユーザには移行期間版を使ってもらうことにします。
次回は新アプリをCocoaPodsで作成して、コードを移行したり整理したりしたいと思います。