web-dev-qa-db-ja.com

iOS7およびiOS8:ユーザーがプッシュ通知のリクエストに対して「いいえ」と言ったことを検出する方法

IOS7とiOS8をターゲットにしたアプリを作成しています。プッシュ通知を送信する許可をユーザーに求めます。しかし、何らかの理由で、プッシュ許可を求められたときに「いいえ」をクリックしても、iOS7もiOS8も_application:didFailToRegisterForRemoteNotificationsWithError_ハンドラーを呼び出さない。

私の質問:ユーザーがプッシュ通知のリクエストを却下したことをiOS7とiOS8の両方でどのように知ることができますか?彼らは要求を拒否しましたか?

私はStackOverflowの回答をたくさん見て、それらが提案するものを実装しましたが、文書化されているようには機能していません。

  • iOS7:ユーザーがリクエストを承認すると、システムは私の_application:didRegisterForRemoteNotificationsWithDeviceToken:_ハンドラーを呼び出します。だから私は彼らがそれを承認したと言うことができます。しかし、ユーザーがリクエストを拒否した場合、_application:didFailToRegisterForRemoteNotificationsWithError_へのコールバックは取得されません。これはバグのようで、ユーザーがリクエストを拒否したことはわかりません。
  • iOS8:ユーザーがリクエストを承認または拒否すると、システムは私の_application:didRegisterUserNotificationSettings_ハンドラーを呼び出しますnotificationSettingsパラメーターを調べて、ユーザーが私の要求を承認または拒否したかどうかを確認できるので、便利です。 ただし、後でisRegisteredForRemoteNotifications()を呼び出すと(たとえば、アプリが後でアクティブになったとき)、ユーザーがリクエストを拒否した場合でも常にtrueが返されます。だから私は誤検知を取得します。これはバグのようで、 他の人もこれに気づいています 更新:後でlet settings = UIApplication.sharedApplication().currentUserNotificationSettings()を呼び出すと、_settings.types_をチェックしてアラートが許可されているかどうかを確認できます。つまり、iOS8の場合、準備が整ったように見えます。

NSUserDefaultsブール値を使用して、ユーザーに許可を付与するように既に要求したかどうかを追跡しています。

テストには、シミュレーターではなく、ハードウェアデバイス(iOS7を搭載したiPhone4SおよびiOS8を搭載したiPhone5)を使用しています。

私は 各テスト後にデバイスをリセットする 、リクエストアラートを再度表示するようにしています。

プッシュ通知に登録する方法は次のとおりです。 ifブランチはiOS8で使用され、elseブランチはiOS7で使用されます。

_    let application = UIApplication.sharedApplication()

    if (application.respondsToSelector("registerUserNotificationSettings:")) {
        let settings = UIUserNotificationSettings(forTypes: .Badge | .Alert | .Sound,
            categories: nil )
        application.registerUserNotificationSettings(settings)
    } else {
        application.registerForRemoteNotificationTypes(.Badge | .Alert | .Sound)
    }
_

(iOS8では、_application:didRegisterUserNotificationSettings:_が呼び出されると、application.registerForRemoteNotifications()が呼び出されます)。

17
Brian Morearty

登録が失敗しなかったため、didFailToRegisterForRemoteNotificationsWithErrorメソッドは呼び出されません。ユーザーがリクエストを拒否したため、メソッドは呼び出されませんでした。

IOS7では、いくつかのことができます。

  1. didRegisterForRemoteNotificationsWithDeviceTokenが呼び出されるまでリモート通知は利用できないと想定します
  2. enabledRemoteNotificationTypesオブジェクトの値UIApplicationを確認してください
6
Paulw11

私はこの同じ問題を回避する方法を見つけようとしていました。

プッシュ通知権限UIAlertが表示されると、アプリの外部から表示されます。ユーザーが「許可しない」または「OK」を選択すると、アプリが再びアクティブになります。

ユーザーにプッシュ権限の入力を求める前に提示しているViewControllerがあります。このビューコントローラーでは、UIApplicationDidBecomeActiveNotificationをリッスンしてから、ビューコントローラーを閉じます。

これはかなりうまく機能していますが、私が見た他のすべてのソリューションは私にはまったく機能していません。

7
Marcus

IOS8以降に対してコンパイルしていると仮定すると、次のデリゲートメソッドを使用できます。

func application(application: UIApplication, didRegisterUserNotificationSettings notificationSettings: UIUserNotificationSettings) {
    print("Notifications status: \(notificationSettings)")
}

次に、didFinishLaunching(またはニーズに適した場所)で、次を呼び出す必要があります。

let app = UIApplication.sharedApplication()
let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
app.registerUserNotificationSettings(settings)
app.registerForRemoteNotifications()

この時点で、ユーザーは通常の「許可/許可しないプロンプト」メッセージでプロンプトが表示されます。ユーザーの選択に関係なく、上記のメソッドが呼び出され、アプリのきめ細かい構成が可能になります。結果は次のようになります。

Notification Status: <UIUserNotificationSettings: 0x7fa261701da0; types: (none);>

Notification Status: <UIUserNotificationSettings: 0x7ff032e21dd0; types: (UIUserNotificationTypeAlert UIUserNotificationTypeBadge UIUserNotificationTypeSound);>

最初のケースでは、ユーザーが通知を拒否したことに気付くでしょう。 2つ目は、許可オプションに関するものです。

2
valvoline