iOS8でのプッシュ通知の実装変更点

iOS8にアプリを対応させるにあたり
機能の追加などに伴いプッシュ通知でも幾つか変更が必要になりました。
変更点と実装を書いておこうと思います。

## 追加された関数と非推奨になった関数
iOS8から通知アクションなどが設定できるようになった影響で、一部の関数が非推奨になり使用できなくなりました。

#### **デバイス登録**
　iOS7まではデバイス登録の関数でアラートやバッジなどの通知の設定も行うことが出来ましたが
　通知アクションの設定が追加されたことで通知の設定は別の関数に分離されました。

```objc:iOS7まで
- (void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types
```
```objc:iOS8
- (void)registerForRemoteNotifications
```
#### **通知の設定登録 New!**
iOS8からデバイス登録関数では設定の登録ができなくなったのでこちらも呼ぶ必要があります。

```objc:iOS8で追加
- (void)registerUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
```
#### **デバイス登録コールバック**

```objc:iOS8でも同じ
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
```
#### **デバイス登録失敗コールバック**

```objc:iOS8でも同じ
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
```
#### **通知の設定登録コールバック New!**
iOS8から分離された通知の設定のコールバックです。

```objc:iOS8で追加
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
```
#### **デバイス登録解除**

```objc:iOS8でも同じ
- (void)unregisterForRemoteNotifications
```
#### **通知の設定取得**
iOS7までは通知の設定を取得することで同時に登録されているか取得していたのですが、iOS8からは登録の有無は別の関数に分離されました。

```objc:iOS7まで
- (UIRemoteNotificationType)enabledRemoteNotificationTypes
```
```objc:iOS8
- (UIUserNotificationSettings *)currentUserNotificationSettings
```
#### **デバイス登録されているか New!**

```objc:iOS8で追加
- (BOOL)isRegisteredForRemoteNotifications
```
## 実装変更
上記をまとめると

* デバイス登録時に設定の登録を呼ぶ
* 設定の登録のコールバックを実装する

追加はこれくらいですね。あとは呼ぶ関数が違うとか列挙型が異なってるとかです。
下記の実装例ではiOS7 SDK(Xcode5)およびiOS8 SDK(Xcode6)でビルドできるように書いていきます。

### デバイス登録

1. SDKで許容するiOSバージョンのマクロ判定でiOS7SDKでビルドが通るようにする
2. respondsToSelectorでメソッドの有効性チェックをして、実行時に関数の使い分けしてる

iOS7SDKでビルド通らなくてもいいなら１はいらないですね。開発環境の都合上、両方でビルドする時期がある場合とかですね。
２に関しても僕は有効性チェックにしていますが、iOSバージョンでもいいとは思います。

```objc
- (void)registerDevice
{
    UIApplication *application = [UIApplication sharedApplication];
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
    // iOS8 SDK の場合の処理
    if ([application respondsToSelector:@selector(registerUserNotificationSettings:)])
    {
        UIUserNotificationType types = UIUserNotificationTypeAlert;
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:types categories:nil];
        [application registerForRemoteNotifications];
        [application registerUserNotificationSettings:settings];
    }else{
        [application registerForRemoteNotificationTypes:(RemoteNotificationTypeAlert)];
    }
#else
    // iOS7 SDK の場合の処理
    [application registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert)];
#endif
}
```

### 設定の登録コールバック
上記のデバイス登録と同じようにiOS7SDKでビルドが通るようにしてるだけです。

```objc
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 80000
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
}
#endif
```

## リンク

[UIApplication Class Reference](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplication_Class/index.html#//apple_ref/doc/uid/TP40006728)
[UIApplicationDelegate Protocol Reference](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIApplicationDelegate_Protocol/index.html#//apple_ref/doc/uid/TP40006786)