回拨方法如果用户拒绝推送通知提示?
我的问题是我想显示一个加载屏幕的初始推送通知提示“该应用程序想发送推送通知。”
所以,如果用户点击yes
我可以继续,然后启动应用程序,然后调用委托方法:
- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { [self hideLoadingScreen]; } - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { [self hideLoadingScreen]; }
但是,如果用户打no
,这些方法都不会被调用,这是有道理的。 我的问题是,是否有不同的委托方法会被拒绝?
我的问题是,如果no
select,加载屏幕永远不会消失。 所以我不知何故需要知道用户何时完成select。
在iOS 7中,系统的推送通知提示出现时,应用程序变为不活动状态,并且UIApplicationWillResignActiveNotification激发。 同样,当用户对提示做出响应(按“是”或“否”)时,应用程序会再次变为活动状态,并且UIApplicationDidBecomeActiveNotification会触发。
所以你可以听这个通知,然后隐藏你的加载屏幕。
注意:显示提示时,主页button,通知中心和控制中心被禁用,因此它们不能触发误报UIApplicationDidBecomeActiveNotification。 但是,如果用户按下lockingbutton,将触发UIApplicationDidBecomeActiveNotification。
您始终可以获取当前允许的通知types:
UIRemoteNotificationType notificationTypes = [[UIApplication sharedApplication] enabledRemoteNotificationTypes];
请记住,用户也可以在电话设置中禁用通知。
如果你检查didRegisterForRemoteNotificationsWithDeviceToken你应该看看你要求的types是否被启用。
你不能只是做以下几点:
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings { BOOL pushEnabled = notificationSettings.types & UIUserNotificationTypeAlert; }
这个方法应该是对那个推送通知提示的callback,并且从那里,你可以检查位掩码来查看推送通知是否被启用。
这里是我在Swift 3中做的。他们的关键是在内部跟踪应用程序的生命周期状态。 当出现推送提示时,应用程序将会退出活动状态,但不会进入后台。 这一切都在我的AppDelegate.swift。
这是一个非常大的黑客,不build议在生产中。 苹果可能会改变这些警报的呈现方式,随时都可能中断。 这是使用运行iOS 9和10的各种iPhone和iPadtesting的。
/// An internal value used to track application lifecycle state enum ApplicationLifecycleState { case willResignActive case didEnterBackground case willEnterForeground case didBecomeActive case unknown } /// This is used purely for tracking the application lifecycle for handling the system push notification alert var internalLifecycleState: ApplicationLifecycleState = .unknown { didSet { // If we're not in the middle of asking for push permissions, none of the below applies, just bail out here if !isAskingForPushPermissions { return } // WARNING: Application lifecycle trickery ahead // The normal application lifecycle calls for backgrounding are as follows: // applicationWillResignActive -> applicationDidEnterBackground -> applicationWillEnterForeground -> applicationDidBecomeActive // However, when the system push notification alert is presented, the application resigns active, but does not enter the background: // applicationWillResignActive -> [user taps on alert] -> applicationDidBecomeActive // We can use this discrepancy to our advantage to detect if the user did not allow push permissions // If applicationDidBecomeActive // AND the previous state was applicationWillResignActive // AND the notification types bitmask is 0, we know that the user did not allow push permissions // User denied permissions if internalLifecycleState == .didBecomeActive && oldValue == .willResignActive && UIApplication.shared.currentUserNotificationSettings?.types.rawValue == 0 { // We're done firePushCompletionBlockAndCleanup(registered: false) } else { // The state below can only be entered on iOS 10 devices. // If the user backgrounds the app while the system alert is being shown, // when the app is foregrounded the alert will dismiss itself without user interaction. // This is the equivalent of the user denying push permissions. // On iOS versions below 10, the user cannot background the app while a system alert is being shown. if #available(iOS 10, *), internalLifecycleState == .didBecomeActive { firePushCompletionBlockAndCleanup(registered: false) } } } } /// Used internally to track if the system push notification alert is currently being presented var isAskingForPushPermissions = false typealias PushNotificationRegistrationCompletionBlock = ((_ registered: Bool) -> Void) // ... func applicationWillResignActive(_ application: UIApplication) { internalLifecycleState = .willResignActive } func applicationDidEnterBackground(_ application: UIApplication) { internalLifecycleState = .didEnterBackground } func applicationWillEnterForeground(_ application: UIApplication) { internalLifecycleState = .willEnterForeground } func applicationDidBecomeActive(_ application: UIApplication) { internalLifecycleState = .didBecomeActive } // ... func setupPushNotifications(_ application: UIApplication = UIApplication.shared, completion: @escaping PushNotificationRegistrationCompletionBlock) { isAskingForPushPermissions = true pushCompletionBlock = completion let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil) application.registerUserNotificationSettings(settings) application.registerForRemoteNotifications() } fileprivate func firePushCompletionBlockAndCleanup(registered: Bool) { pushCompletionBlock?(registered) pushCompletionBlock = nil isAskingForPushPermissions = false } func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { // application:didRegisterForRemoteNotificationsWithDeviceToken may be called more than once (once for each notification type) // By checking that the notification types bitmask is greater than 0, we can find the final time this is called (after the user actually tapped "allow") // If the user denied push permissions, this function is never called with a positive notification type bitmask value if UIApplication.shared.currentUserNotificationSettings?.types.rawValue ?? 0 > 0 { firePushCompletionBlockAndCleanup(registered: true) } } func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("Failed to register for notifications with error: " + error.localizedDescription) firePushCompletionBlockAndCleanup(registered: false) }
用法:
appDelegate.setupPushNotifications(completion: { [weak self] (registered) in // If registered is false, the user denied permissions })
我猜你可以有一个BOOLvariables来检查你的AppDelegate,因为除了使用外部API似乎没有办法。 看到这个
AppDelegate.m // declare a BOOL BOOL allow = NO; - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { allow = YES; [self hideLoadingScreen]; } - (void)application:(UIApplication*)application didFailToRegisterForRemoteNotificationsWithError:(NSError*)error { allow = YES; [self hiedLoadingScreen]; }
现在我猜你可以访问这个BOOLvariables来区分什么时候不允许被按下或没有。
这里有一个SWIFT 2代码示例,对于你们来说…这有点复杂,但是我希望我的意见能够帮助你理解它。
定义variables
var appDidBecomeActiveCount = 0 var userDefaults:NSUserDefaults!
AppDelegate – didFinishLaunchingWithOptions
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { userDefaults = NSUserDefaults.standardUserDefaults() if userDefaults.valueForKey("FirstLaunche") == nil { userDefaults.setBool(true, forKey: "FirstLaunche") userDefaults.synchronize() } // Register for notification //iOS 8+ let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: [UIUserNotificationType.Alert , UIUserNotificationType.Badge ,UIUserNotificationType.Sound], categories: nil) UIApplication.sharedApplication().registerUserNotificationSettings(settings) UIApplication.sharedApplication().registerForRemoteNotifications() }
AppDelegate – applicationDidBecomeActive
func applicationDidBecomeActive(application: UIApplication) { //Delay until alert get dismissed and notification type setted in app delay(0.5, closure: { () -> () in self.checkTheDilemma() }) } //I love this short method <3_<3 func delay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
检查行动
func checkTheDilemma (){ //Checking if this user turned off push notifications or didn't allow it at all let notificationType = UIApplication.sharedApplication().currentUserNotificationSettings()?.types if userDefaults.valueForKey("FirstLaunche") as! Bool == true { //User now is asked for notification permission because it's app's first launche // if appDidBecomeActiveCount == 0 --> Pop up message will appeare // if appDidBecomeActiveCount == 1 --> Pop up message dismissed // if notificationType?.rawValue == 0 --> Notifications off // if notificationType?.rawValue > 0 --> Notifications on if notificationType?.rawValue == 0 && appDidBecomeActiveCount == 1 { //If user disabled notifications from pop up alert // ** User just tapped "Don't allow" btn :\ // Do what ever you are here for //Now set FirstLaunche = false userDefaults.setBool(false, forKey: "FirstLaunche") userDefaults.synchronize() } } else { if notificationType?.rawValue == 0 && appDidBecomeActiveCount == 0 { // This guy is not registered for push notification // ** User disabled notifications in past (because this is not his first launch) } } appDidBecomeActiveCount++ }