Swiftでのローカル通知・リモート通知の実装メモ


# はじめに

初めてiOSでの通知を実装したので実装手順の覚書です。
このエントリでは通知に関するアプリ側の実装に関して記述をします。
リモート通知を行うサーバーサイドはmBaaS(mobile backend as a Service)を使用する前提とします。
記述コードはひとまずSwift 2.3となっています。

# 概要
- 通知の種類  
ローカル通知とリモート通知の違い・特徴  
サイレントプッシュの特徴
- リモート通知の事前準備  
リモート通知を実装する上で必要な準備
- 実装  
実際に実装する上でのポイント
- Tips  
実装する上での留意点
- 参考文献

# 通知の種類

iOSではローカル通知とリモート通知の2種類があります。
iOS 7からサイレントリモート通知が使えるようになりました。

大まかな用途は以下の通りです。

- ローカル通知
リマインダーアプリやタイマーなどアプリ単体で  
アプリがフォアグラウンド以外なら通知が表示される
- リモート通知  
外部のサーバーから端末に対して通知したい  
→主にWebサービスと連携するアプリで使用  
アプリがフォアグラウンド以外なら通知が表示される
- サイレントリモート通知  
リモート通知と仕組みは同様だが通知は表示されず、アプリにバックグラウンドで何か処理を実行させたい場合のトリガーとしてサーバーから通知を送る仕組みです。

# リモート通知の事前準備

リモート通知を実装する上で必要になる作業です。
ここでは既存のmBaaSを使用する前提とします。

## mBaaSの選定

リモート通知を実現するためにmBaaSを使用します。
主に以下のような既存サービスが存在しています。

- Firebase
- GrowthPush
- AdobePush

それぞれ細かい仕様の違いはありますが、基本的な機能は同じはずです。

## リモート通知用の証明書の作成

リモート通知で使用するSSL証明書を作成します。
以下のページを参考に作成しました。

Apple Push Notification Serviceを使ってiOSにプッシュ通知をするために必要な証明書の準備方法
http://d.hatena.ne.jp/samril/20130902/1378198909

DevelopmentとProduction向けのSSL証明書を作成します。
この手順で作成されるpemファイルをmBaaSへ登録します。

## mBaaSの設定

作成されたpemファイルやAppIDなどをmBaaSへ設定します。
mBaasごとの手順を確認してください。

## Push Notificationsの有効化

Apple Developer Programにログインして対象となるApp IDのPush Notificationsを有効にします。
有効後のProvisioning Fileを再取得して開発PCへ反映させます。

## アプリ側の設定

対象アプリのTARGETSのCapabilitiesを選択してPush Notificationsを有効にします。
Provisioning FileのPush Notificationsが有効になっていないとエラーになりますので、その場合はProvisioning Fileを確認します。

# 実装

## ローカル通知・リモート通知共通

ひとまず通知を実装するため、AppDelegate.swiftにまとめて実装していきます。

### リモート通知を有効化する初期設定を実装

こちらを参考に記述します。
Xcode6でiOS8へPush通知が送れない場合の解決方法
http://qiita.com/peromasamune/items/90970e9f9d5c34d21cfd


### 通知からアプリが起動した場合の処理を実装

```swift:AppDelegate.swift
    func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool
    {
            if let launchOptions = launchOptions {
            	// アプリが起動していない場合に通知からタップされた場合の処理を実装
            }
        }
    }
```

### アプリがフォアグラウンド時の通知受信かバックグラウンド時に通知タップされた場合の処理を実装

```swift:AppDelegate.swift
    func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) {
        switch application.applicationState {
        case .Active:
            // アプリフォアグラウンド時の処理
        case .Inactive:
            // アプリバッググラウンド時の処理
        default:
            break
        }
    }
```

### mBaaSへデバイストークンを登録する処理を実装

```swift:AppDelegate.swift
    func application(application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) {
      // デバイストークン登録処理を実装
    }
```

# Tips

## プッシュ通知の証明書の有効期限

有効期限が1年間となっており、毎年更新が必要です。
期限切れになるとプッシュが届かなくなります。

## サイレントリモート通知の用途

サイレントリモート通知はアプリがフォアグラウンドかバックグラウンドにある状態でのみ動作します。
アプリが起動されていない場合は通知して動作することができません。

## アプリがフォアグラウンド時のリモート通知を受け取った場合の実装

アプリを使用中(フォアグラウンド時)にリモート通知を受け取った場合、バックグラウンド時の通知が表示されません。
独自にトーストを表示するなどの対応が必要になります。

Toast-Swift
https://github.com/scalessec/Toast-Swift

## 通知の削除

アプリ起動後に通知センターの通知を削除したい場合があるかもしれません。対処方法は以下の通りです。

### ローカル通知

全て削除することも可能、事前にキーを設定することで任意の通知のみ削除することも可能です。
詳しくは以下のページを参照ください。

[iOS] ローカル通知について
http://dev.classmethod.jp/smartphone/ios-local-notification/

### リモート通知

バッジを0にすることでリモート通知を削除することが可能です。
バッジのみ元に戻したい場合は、バッジ数を一時変数に退避してバッジを元に戻せば良いです。

```swift
    UIApplication.sharedApplication().applicationIconBadgeNumber = 0
```

# 参考文献

以下のドキュメントを参考にしました。

Local および
Push Notification プログラミングガイド
https://developer.apple.com/jp/documentation/RemoteNotificationsPG.pdf


# 最後に

認識違い・過不足などあればご指摘いただければ幸いです。
最後までお読みいただきありがとうございました。