iOS8で導入されたアクション付きPush通知を試してみる

エンジニアブログをご覧のみなさま、こんにちは。
マネーフォワードでiOSエンジニアをしてます西信です。
 
ついに、iPhone6が発売になり、iOS8が公開されました。
そこで今回は、iOS8で導入された通知アクション付きのPush通知を試してみようと思います。
 
いきなりですが、今回実装したサンプルコードです(笑)

実装


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //各通知アクションの生成 UIMutableUserNotificationAction *action1 = [[UIMutableUserNotificationAction alloc] init]; action1.title = @"はい"; action1.identifier = @"id1"; UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init]; action2.title = @"いいえ"; action2.identifier = @"id2"; UIMutableUserNotificationAction *action3 = [[UIMutableUserNotificationAction alloc] init]; action3.title = @"内容による"; action3.identifier = @"id3"; UIMutableUserNotificationAction *action4 = [[UIMutableUserNotificationAction alloc] init]; action4.title = @"・・・"; action4.identifier = @"id4"; //通知カテゴリに各アクションを登録 UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init]; category.identifier = @"ACTION_CATEGORY"; [category setActions:@[action1, action2, action3, action4] forContext:UIUserNotificationActionContextDefault]; UIUserNotificationType types = UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert; //カテゴリをセッティングに設定 UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:[NSSet setWithObject:category]]; //プッシュ通知に登録 [[UIApplication sharedApplication] registerUserNotificationSettings:mySettings]; return YES; } - (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { //register to receive notifications [application registerForRemoteNotifications]; } //デバイストークンの取得 -(void) application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { NSString *tokenAsString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]]; tokenAsString = [tokenAsString stringByReplacingOccurrencesOfString:@" " withString:@""]; } // 選択アクションに応じた処理 - (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler { if ([identifier isEqualToString:@"id1"]) { // はい の処理 } if ([identifier isEqualToString:@"id2"]) { // いいえ の処理 } if ([identifier isEqualToString:@"id3"]) { // 内容による の処理 } if ([identifier isEqualToString:@"id3"]) { // ・・・ の処理 } // 終了時に必ず呼ぶこと completionHandler(); }

これでAPNsからプッシュ通知を受けると下記のようにアクションがつきます。
(※デバイストークンを受け取るサーバサイドは割愛します。)

[バナー形式]

Screen Shot 2014-10-01 at 21.05.08
Screen Shot 2014-10-01 at 21.09.07
 
[ダイアログ形式]
Screen Shot 2014-10-01 at 21.10.40
Screen Shot 2014-10-01 at 21.10.53
 

説明

従来からの変更点としては、iOS8ではデバイストークンの取得方法が変わっています。

従来の

registerForRemoteNotificationTypes:

でなく、iOS8からは、

registerUserNotificationSettings:

を定義します。

また、

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings

を定義し、

[application registerForRemoteNotifications];

を呼び出す必要があるようです。
ここまでしないとデバイストークンを取得する、

- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken

が呼ばれません。

通知アクションをつけるためには、UIMutableUserNotificationActionを生成します。
titleプロパティには画面に表示する文字、identifierプロパティには一意のアクション識別子を定義します。
端末の設定により通知スタイルがバナーになっている場合は最大2つ、通知スタイルがダイアログになっている場合は4つまでアクションを表示することができます。

今回はダイアログを想定して4つ生成します。

    UIMutableUserNotificationAction *action1 = [[UIMutableUserNotificationAction alloc] init];
    action1.title = @"はい";
    action1.identifier = @"id1";

    UIMutableUserNotificationAction *action2 = [[UIMutableUserNotificationAction alloc] init];
    action2.title = @"いいえ";
    action2.identifier = @"id2";

    UIMutableUserNotificationAction *action3 = [[UIMutableUserNotificationAction alloc] init];
    action3.title = @"内容による";
    action3.identifier = @"id3";

    UIMutableUserNotificationAction *action4 = [[UIMutableUserNotificationAction alloc] init];
    action4.title = @"・・・";
    action4.identifier = @"id4";

次に、作成した通知アクションを通知カテゴリに登録します。

    UIMutableUserNotificationCategory *category = [[UIMutableUserNotificationCategory alloc] init];
    category.identifier = @"ACTION_CATEGORY";
    [category setActions:@[action1, action2, action3, action4] forContext:UIUserNotificationActionContextDefault];

そして、カテゴリをセッティングに設定し、プッシュ通知に登録します。

UIUserNotificationType types = UIUserNotificationTypeBadge |  UIUserNotificationTypeSound | UIUserNotificationTypeAlert;
UIUserNotificationSettings *mySettings = [UIUserNotificationSettings settingsForTypes:types categories:[NSSet setWithObject:category]];
[[UIApplication sharedApplication] registerUserNotificationSettings:mySettings];

APNsサーバから送るJSONの形式は下記のようにします。

{
  "aps" : {
    "alert" : "私のお願いを聞いてくれませんか?",
    "category" : "ACTION_CATEGORY"
  }
}

通知アクションを使うためにJSONではcategoryキーを定義する必要があります。
設定する値は、UIMutableUserNotificationCategoryのidentifierに設定した値と同一にする必要があります。
 
最後にユーザがアクションを選択すると、

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void(^)())completionHandler

が呼ばれるので、アクションのidentifierの値に応じて処理を分岐することができます。

- (void)application:(UIApplication *)application handleActionWithIdentifier:(NSString *)identifier forRemoteNotification:(NSDictionary *)userInfo completionHandler:(void (^)())completionHandler {

    if ([identifier isEqualToString:@"id1"]) {
        // はい の処理

    }

    if ([identifier isEqualToString:@"id2"]) {
        // いいえ の処理

    }

    if ([identifier isEqualToString:@"id3"]) {
        // 内容による の処理

    }

    if ([identifier isEqualToString:@"id3"]) {
        // ・・・ の処理

    }

    // 終了時に必ず呼ぶこと
    completionHandler();
}

この機能を使って色々と面白いことができそうですね。

最後に

マネーフォワードでは、新しい事にチャレンジできるiOSエンジニアを募集しています!
最高のサービスを一緒に創っていきましょう!

マネーフォワード採用サイト
https://recruit.moneyforward.com/

お金のNo.1サービス!iOSエンジニアWanted!
https://www.wantedly.com/projects/9983

Pocket