1. Qiita
  2. 投稿
  3. Swift

SwiftでPush通知

  • 192
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

※iOS8でのやり方がわかったので一番下に追記しました

SwiftでPush通知を実装してみました。
証明書の取得等はこちらを参考にしています。

【iOSでプッシュ通知を実装する方法の超詳細まとめ(前編)】
http://www.lancork.net/2013/08/how-to-ios-push-first/

【iOSでプッシュ通知を実装する方法の超詳細まとめ(後編)】
http://www.lancork.net/2013/08/how-to-ios-push-second/

元記事:http://sawapi.hatenablog.com/entry/2014/06/08/230719

コードの解説

Push通知を有効にする

func application( application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary? ) -> Bool {

    application.registerForRemoteNotificationTypes(
        UIRemoteNotificationType.Badge | 
        UIRemoteNotificationType.Sound |
        UIRemoteNotificationType.Alert )

    return true
}

AppDelegate.swiftのapplication didFinishLaunchingWithOptionsにて
application.registerForRemoteNotificationTypesを呼び出し、有効にするものを指定します。

  • UIRemoteNotificationType.Badge・・・アイコンバッジ
  • UIRemoteNotificationType.Sound・・・Push通知時になる音
  • UIRemoteNotificationType.Alert・・・Push通知時に表示される文字列

上記の処理が成功するとapplication didRegisterForRemoteNotificationsWithDeviceTokenが呼ばれるのでその中でデバイストークンを取得します。

デバイストークンの取得

func application( application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData ) {

    // <>と" "(空白)を取る
    var characterSet: NSCharacterSet = NSCharacterSet( charactersInString: "<>" )

    var deviceTokenString: String = ( deviceToken.description as NSString )
                                        .stringByTrimmingCharactersInSet( characterSet )
                                        .stringByReplacingOccurrencesOfString( " ", withString: "" ) as String

    println( deviceTokenString )

}

devideToken.descriptionには、

<00000000 11111111 22222222 33333333 aaaaaaaa bbbbbbbb cccccccc dddddddd>

というような文字列で入っているため、"<"と">"と" (スペース)"を取る必要があります。
Swiftの文字の整形の仕方が分からず、、一旦NSStringに変換し、余分な文字を取り除きました。
( いい方法がありましたら教えて下さい。。。)

上記までを実行するとデバイストークンを取得できるのでメモしておきます。

Push通知が届くかテスト

Push通知がちゃんと届くかテストするために以下のスクリプトでテストしてみました。

<?php
$deviceToken = '************';

// 送信する文字列
$alert = 'Push test.';

// バッジ
$badge = 1;

$body = array();
$body['aps'] = array( 'alert' => $alert );
$body['aps']['badge'] = $badge;

// SSL証明書
$cert = '********.pem';

$url = 'ssl://gateway.sandbox.push.apple.com:2195'; // 開発用
//$url = 'ssl://gateway.push.apple.com:2195'; // 本番用

$context = stream_context_create();
stream_context_set_option( $context, 'ssl', 'local_cert', $cert );
$fp = stream_socket_client( $url, $err, $errstr, 60, STREAM_CLIENT_CONNECT, $context );

if( !$fp ) {

    echo 'Failed to connect.' . PHP_EOL;
    exit( 1 );

}

$payload = json_encode( $body );
$message = chr( 0 ) . pack( 'n', 32 ) . pack( 'H*', $deviceToken ) . pack( 'n', strlen($payload ) ) . $payload;

print 'send message:' . $payload . PHP_EOL;

fwrite( $fp, $message );
fclose( $fp );

以下のように通知がきたら成功です。
screenshot_push.png

ソースコード

gistにあげました。
https://gist.github.com/sawapi/a7cee65e4ad95578044d

(´・ω・`)

ここまで書いて気づいたんですが、registerForRemoteNotificationTypesメソッドは
iOS8からDeprecatedになってるんですね。。。
試しに新しいやり方でやってみましたがうまくいかない、、というか
やり方がよくわかりませんでした。

var types: UIUserNotificationType = UIUserNotificationType.Badge |
                                   UIUserNotificationType.Alert |
                                   UIUserNotificationType.Sound


var settings: UIUserNotificationSettings = UIUserNotificationSettings.settingsForTypes( types, categories: nil )
application.registerUserNotificationSettings( settings )

application.registerForRemoteNotifications()

これでできると思ったんですが、こんなエラーがでます(´・ω・`)

'settingsForTypes' is unavailable: use object construction 'UIUserNotificationSettings(forTypes:categories:)'
UIUserNotificationSettings.settingsForTypes

Objective-Cだとこんな感じでうまくいってるみたいなんですが。。
http://stackoverflow.com/questions/24049266/get-the-push-notification-list-on-ios8

やり方わかったら書き直します(´・ω・`)

※6/13追記
やり方分かりました。
エラーログにちゃんと書いてあるのに気付かなかった。。。

func application( application: UIApplication, didFinishLaunchingWithOptions launchOptions: NSDictionary? ) -> Bool {

    var types: UIUserNotificationType = UIUserNotificationType.Badge |
        UIUserNotificationType.Alert |
        UIUserNotificationType.Sound

    var settings: UIUserNotificationSettings = UIUserNotificationSettings( forTypes: types, categories: nil )

    application.registerUserNotificationSettings( settings )
    application.registerForRemoteNotifications()

    return true
}

これでできそうですー!