Money Forward Developers Blog

株式会社マネーフォワード公式開発者向けブログです。技術や開発手法、イベント登壇などを発信します。サービスに関するご質問は、各サービス窓口までご連絡ください。

20230215130734

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