PUSH通知機能を持ったiPhoneアプリを作る（デバイストークンの登録とメッセージの受信）

FacebookやTwitter、LINEなど多くのサービスで使われているPUSH通知機能を実装してみます。証明書の準備やサーバ側の実装などの説明は省きますので、詳細に知りたい方は下記をご参考下さい。  
* [PUSH通知機能を持ったiPhoneアプリを作る（証明書の作成）](http://himaratsu.hatenablog.com/entry/objc/push_certification)<a href="http://b.hatena.ne.jp/entry/http://himaratsu.hatenablog.com/entry/objc/push_certification" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://himaratsu.hatenablog.com/entry/objc/push_certification" alt="" /></a>
* <a style="color:#0070C5;" href="http://d.hatena.ne.jp/moto_maka/20130412/1365708877" target="_blank">iPhoneアプリにPush通知機能を実装する方法のまとめ - もとまか日記</a><a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/moto_maka/20130412/1365708877" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/moto_maka/20130412/1365708877" alt="" /></a>  

## デバイスの登録
「デバイストークン」をサーバ側へ送信します。  PUSH通知を送る際には、このデバイストークンを指定してメッセージを送ります。  

``` objc
// アプリ起動時
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  // PUSH通知を登録
  [[UIApplication sharedApplication]
	registerForRemoteNotificationTypes:
   (UIRemoteNotificationTypeBadge|
    UIRemoteNotificationTypeSound|
    UIRemoteNotificationTypeAlert)];
}

// デバイストークン発行成功
- (void)application:(UIApplication*)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)devToken{
  NSLog(@"deviceToken: %@", devToken);

  // デバイストークンをサーバに送信し、登録する
}

// デバイストークン発行失敗
- (void)application:(UIApplication*)app didFailToRegisterForRemoteNotificationsWithError:(NSError*)err{
  NSLog(@"Errorinregistration.Error:%@",err);
}
```

アプリ起動時に`registerForRemoteNotificationTypes`を呼び出し、デバイストークンの発行をリクエストします。  
成功すると`didRegisterForRemoteNotificationsWithDeviceToken:`が呼ばれます。引数としてdevTokenが渡されるので、これをサーバに送信して登録処理を行います。  
また、デバイストークンの発行に失敗した場合は`didFailToRegisterForRemoteNotificationsWithError`が呼ばれます。  


## メッセージの受信
PUSH通知を受け取った際には、以下のいずれかのメソッドが呼ばれます。

* didFinishLaunchingWithOptions
* didReceiveRemoteNotification
  

#### アプリが起動していない時に、PUSH通知からアプリを起動した場合
``` objc
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
  ...
  NSDictionary *userInfo
  = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
  if (userInfo != nil) {
    // ここに処理        
  }
  ...
}
```

#### アプリがフォアグラウンドで起動している時にPUSH通知を受信した場合
``` objc
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{  
  if (application.applicationState == UIApplicationStateActive)
  {
    ...
    // ここに処理
    ...
  }    
}
```

#### アプリがバックグラウンドで起動している時に、PUSH通知からアクティブになった場合
``` objc
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{  
  if (application.applicationState == UIApplicationStateInactive)
  {
    ...
    // ここに処理
    ...
  }    
}
```

## PUSH通知に含まれるメッセージを取り出す
PUSH通知で送るメッセージにはKey-Valueの形でデータを持たせることができます。  
userInfoオブジェクトに格納されているので、そこから取り出して扱います。  

#### アプリが起動していない時に、PUSH通知からアプリ起動
``` objc
    NSDictionary *userInfo
    = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
    if (userInfo != nil) {
      NSDictionary *message = [userInfo objectForKey:@"message"];
      // messageを使った処理
    }
```

#### アプリがフォアグランドで起動時にPUSH通知を受信 or バックグラウンドで起動時に、PUSH通知からアクティブに
``` objc
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
  NSDictionary *message = [userInfo objectForKey:@"message"];   
  // messageを使った処理
}

```

このようにしてデータを取り出すことができます。  
ここで、`message`というキーはサーバ側でデータを格納する時に決めた任意の文字列です。  

## 参考リンク
* <a style="color:#0070C5;" href="http://d.hatena.ne.jp/shu223/20110828/1314516533" target="_blank">Push Notification おさらい - Over&Out その後</a><a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/shu223/20110828/1314516533" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/shu223/20110828/1314516533" alt="" /></a>  
* <a style="color:#0070C5;" href="http://d.hatena.ne.jp/MonteCut/20120827/1346079444" target="_blank">iOS + PHPでPush Notificationを実装する - モンテカットの開発日記</a><a href="http://b.hatena.ne.jp/entry/http://d.hatena.ne.jp/MonteCut/20120827/1346079444" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://d.hatena.ne.jp/MonteCut/20120827/1346079444" alt="" /></a>
  
  
## 元ネタ
* [PUSH通知機能を持ったiPhoneアプリを作る（デバイストークンの登録とメッセージの受信)](http://himaratsu.hatenablog.com/entry/objc/push)<a href="http://b.hatena.ne.jp/entry/http://himaratsu.hatenablog.com/entry/objc/push" target="_blank"><img src="http://b.hatena.ne.jp/entry/image/http://himaratsu.hatenablog.com/entry/objc/push" alt="" /></a>