/ objc

iOS8でプッシュ通知を使ったりバッジを使ったり

今までプッシュ通知の利用を宣言するのに使ってたメソッドregisterForRemoteNotificationTypesがiOS8からdeprecatedに変わっていたのでメモ

プッシュ通知の利用するとき

iOS7以前の場合

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];

iOS8以降の場合

        [[UIApplication sharedApplication] registerForRemoteNotifications];
        UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound)
                                                                                             categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];

実装はこんな感じにした気がする

    #if !TARGET_IPHONE_SIMULATOR
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
    #endif
    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) {
        [[UIApplication sharedApplication] registerForRemoteNotifications];
        UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:(UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound)
                                                                                             categories:nil];
        [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    }

※ この[[UIApplication sharedApplication] registerForRemoteNotificationTypes:]はdeprecatedなので消した方がいい


バッジを利用するとき

iOS7系も8系も値の設定方法自体は変わってなかったけど、
iOS8でregisterForRemoteNotificationTypesが追加されたことによって
バッジの値表示フラグの確認が必要になった。

iOS7以前の場合

[UIApplication sharedApplication].applicationIconBadgeNumber = <NSInteger>;

iOS8以降の場合

[[UIApplication sharedApplication] currentUserNotificationSettings].types
有効な設定値が取得できるのでフラグを確認してからバッジの値をセットする。
値を確認しなかった場合の挙動は確認してない。

if ([[UIApplication sharedApplication] currentUserNotificationSettings].types & UIUserNotificationTypeBadge) {
    [UIApplication sharedApplication].applicationIconBadgeNumber = iconBadgeNumber;
}

実装はこんな感じにした気がする

iOS7.1以前のOS、または8系以降で UIUserNotificationTypeBadge が設定されてたらバッジの値を更新

if ((floor(NSFoundationVersionNumber) < NSFoundationVersionNumber_iOS_8_0) ||
    (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0 && [[UIApplication sharedApplication] currentUserNotificationSettings].types & UIUserNotificationTypeBadge)) {
    [UIApplication sharedApplication].applicationIconBadgeNumber = iconBadgeNumber;
}


## まとめ(2015/04/06修正)
これスニペット的なやつ

import "AppDelegate.h"

/** メソッドと行数を出力するマクロ */

define LOGF() NSLog(@"%s:%d", PRETTY_FUNCTION, LINE)

@interface AppDelegate ()
@property (nonatomic, strong) NSData *deviceToken;

/** プッシュ通知利用登録 */

  • (void)registRemoteNotification;
    /** プッシュ通知利用解除 */
  • (void)unregistRemoteNotification;
    /** バッジ件数の更新 */
  • (void)updateIconBadgeNumber:(NSInteger)iconBadgeNumber;
    /** AppDelegateインスタンスの取得 */
  • (instancetype)instance;

@end

@implementation AppDelegate

pragma mark - AppDelegate methods

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    [self registRemoteNotification];
    return YES;
    }

pragma mark - AppDelegate PushNotification Setting methods

/** アプリが通知を受信した場合に呼ばれる。(ユーザが通知をタップした時) */

  • (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo {
    LOGF();
    NSLog(@"プッシュ通知を受信しました");
    }

/** デバイストークンを取得 */

  • (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
    LOGF();
    NSLog(@"deviceTokenを受信しました。 deviceToken=%@ ", deviceToken);
    self.deviceToken = deviceToken;
    }

/** プッシュ通知利用登録に失敗 */

  • (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
    LOGF();
    NSLog(@"error: %@", error);
    }

/**
iOS8以降で追加されたプッシュ通知利用登録用メソッド

  • registerUserNotificationSettings:を呼ぶと呼ばれる。
    UIApplicationの- registerForRemoteNotificationsは、シミュレータで実行すると不要なログが出力される
    */
  • (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    LOGF();

if !TARGET_IPHONE_SIMULATOR

[application registerForRemoteNotifications];

endif

}

pragma mark - PushNotification methods

/**
プッシュ通知に利用するタイプの設定
iOS7系以前と8系以降で異なるのでラップする
*/

  • (NSInteger)notificationSettingType {
    LOGF();
    NSInteger type;
    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) {
    /*
    UIUserNotificationTypeNone = 0,
    UIUserNotificationTypeBadge = 1 << 0
    UIUserNotificationTypeSound = 1 << 1
    UIUserNotificationTypeAlert = 1 << 2
    /
    type = (UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert );
    }
    else {
    /

    UIRemoteNotificationTypeは実際のところNSIntegerなので、
    NSIntegerとして定義すればワーニングを減らせる。

       UIRemoteNotificationTypeNone    = 0,
       UIRemoteNotificationTypeBadge   = 1 << 0,
       UIRemoteNotificationTypeSound   = 1 << 1,
       UIRemoteNotificationTypeAlert   = 1 << 2,
       */
      type = (1 << 0 | 1 << 1 | 1 << 2);
    

    }
    return type;
    }

  • (void)registRemoteNotification {
    LOGF();
    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) {
    UIUserNotificationSettings* notificationSettings = [UIUserNotificationSettings settingsForTypes:[self notificationSettingType]
    categories:nil];
    [[UIApplication sharedApplication] registerUserNotificationSettings:notificationSettings];
    }
    else {

if !TARGET_IPHONE_SIMULATOR

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:[self notificationSettingType]];

endif

}

}

  • (void)unregistRemoteNotification {
    LOGF();
    [[UIApplication sharedApplication] unregisterForRemoteNotifications];
    }

  • (void)updateIconBadgeNumber:(NSInteger)iconBadgeNumber {
    LOGF();
    UIApplication application = [UIApplication sharedApplication];
    if (floor(NSFoundationVersionNumber) >= NSFoundationVersionNumber_iOS_8_0) {
    // iOS8 and lator
    if ([application currentUserNotificationSettings].types & UIUserNotificationTypeBadge) {
    /

    バッチの更新処理
    iOS8系の場合は[[UIApplication sharedApplication] currentUserNotificationSettings]で
    更新可能か判断する必要がある
    */
    application.applicationIconBadgeNumber = iconBadgeNumber;
    }
    }
    else {
    // under iOS7
    application.applicationIconBadgeNumber = iconBadgeNumber;
    }
    }

pragma mark - Class methods

  • (instancetype)instance {
    return (AppDelegate *)[UIApplication sharedApplication].delegate;
    }

@end