読者です 読者をやめる 読者になる 読者になる

てくてくテック

気ままに開発のメモを書いていこうと思います。主にSwiftかと。

Swift3でPush通知から起動の時の、userinfo取得でちょっと迷った

はじめに

Swift2.2からSwift3に移行する際に少し詰まった事をメモします。
アプリがキルされている状態からPush通知で起動した時にuserinfoを取得する際のObjectの型宣言をどうするのか?というお話です。

詰まった内容

そもそも実装したい内容

Push通知からアプリを起動した時に、Push通知の内容から画面の遷移をさせる機能を実装したいです。

基本的には、AppDelegateのdidReceiveRemoteNotification において、userinfoからデータを取得すればいいのですが、
こちらにあるように、アプリがキルされている状態からPush通知でアプリを起動するときは、AppDelegateのdidReceiveRemoteNotificationではなくdidFinishLaunchingWithOptionsで通知情報を取得する必要があります。

Swift3に対応

自動コンバートの差分

自動コンバートによる差分は定数の扱い方が変わっただけでした。

-            if let userInfo = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] {
+            if let userInfo = launchOptions?[UIApplicationLaunchOptionsKey.remoteNotification] {

自動コンバートでの問題

この状態のまま、userinfo["title"]などのようにuserinfo内のデータにアクセスしようとすると Type 'Any' has no subscript members というエラーがでます。
これは、launchOptionsの型が [NSObject: AnyObject]から [UIApplicationLaunchOptionsKey: Any] に変わっていることに由来します。
ちなみにこのAnyObjectからAnyに変更される話については昨日投稿しているのでそちらを参照してください。

対応方法

AppleのReferenceによると、UIApplicationLaunchOptionsKey.remoteNotificationの型は NSDictionary らしいので、userinfoを NSDictionaryとして扱えば良いです。(改めて見直すと、func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) と同じということですね)

ちなみに私は下記のように書きました。

if let userInfo = launchOptions?  [UIApplicationLaunchOptionsKey.remoteNotification] as? [AnyHashable : Any] {
  // hogehoge
}

最後に

Swift3対応中にPush通知で起動した際のuserinfoの取得で詰まった件について書きました。
Swift3ではAnyObjectとAnyが変わっていて地味なところで挙動が変わるので ArrayやDictionary系はドキュメントをきちんと読むべきですね。