Firebase iOS 11 在按钮按下后要求用户通知

Posted

技术标签:

【中文标题】Firebase iOS 11 在按钮按下后要求用户通知【英文标题】:Firebase iOS 11 Ask for user notifications after button push 【发布时间】:2017-12-02 19:47:52 【问题描述】:

我正在使用 Firebase 在 ios 11 上启用推送通知。我试图仅在按下按钮后询问用户的通知权限。

目前,应用在加载时会立即请求用户许可。按下按钮后,我想在 EnableNotificationViewController.swift 类中请求此权限。

AppDelegate.swift

import UIKit
import Firebase
import FBSDKCoreKit
import UserNotifications
import FirebaseInstanceID
import FirebaseMessaging

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate, MessagingDelegate 

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 
        // Override point for customization after application launch.

        FirebaseApp.configure()

        // [START set_messaging_delegate]
        Messaging.messaging().delegate = self


        if #available(iOS 10.0, *) 
            // For iOS 10 display notification (sent via APNS)
            UNUserNotificationCenter.current().delegate = self

            let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
            UNUserNotificationCenter.current().requestAuthorization(
                options: authOptions,
                completionHandler: _, _ in )
         else 
            let settings: UIUserNotificationSettings =
                UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
            application.registerUserNotificationSettings(settings)
        

        application.registerForRemoteNotifications()

        FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
        return true
    

    func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool 
        return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
    

    func applicationWillResignActive(_ application: UIApplication) 
        // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
        // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
    

    func applicationDidEnterBackground(_ application: UIApplication) 
        // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
        // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
    

    func applicationWillEnterForeground(_ application: UIApplication) 
        // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
    

    func applicationDidBecomeActive(_ application: UIApplication) 
        // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
        FBSDKAppEvents.activateApp()
    

    func applicationWillTerminate(_ application: UIApplication) 
        // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
    

    // MARK: - Notifications

    // The callback to handle data message received via FCM for devices running iOS 10 or above.
    func application(received remoteMessage: MessagingRemoteMessage) 
        print(remoteMessage.appData)
    



EnableLocationViewController.swift

import UIKit
import Spring
import Firebase

class EnableNotificationsViewController: UIViewController 

    // MARK: - Outlets
    @IBOutlet weak var textLabel: DesignableLabel!

    // MARK: - View Did Load
    override func viewDidLoad() 
        super.viewDidLoad()

    

    // MARK: - Actions
    @IBAction func notificationButton(_ sender: UIButton) 

    



【问题讨论】:

【参考方案1】:

您需要将远程通知权限请求移动到 AppDelegate 中的一个方法中,然后从名为 EnableNotificationsViewController 的 ViewController 中调用此方法。

让我们从AppDelegate 开始并添加registerAPNSServicesForApplication 方法:

///- register with APNS
func registerAPNSServicesForApplication(_ application: UIApplication,withBlock block: @escaping (_ granted:Bool) -> (Void)) 

    // [START register_for_notifications]
    if #available(iOS 10.0, *) 
        let authOptions: UNAuthorizationOptions = [.alert, .badge, .sound]
        UNUserNotificationCenter.current().requestAuthorization(
            options: authOptions,
            completionHandler: granted, error in

                if granted == true

                    DispatchQueue.main.async 
                        application.registerForRemoteNotifications()
                    

                    // For iOS 10 display notification (sent via APNS)
                    UNUserNotificationCenter.current().delegate = self

                

                block(granted)
        )

     else 

        let settings: UIUserNotificationSettings =
            UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()

    


然后从您的EnableNotificationsViewController 调用 AppDelegate 中的方法来请求权限,这样您就知道 iOS 10 及更高版本您将拥有权限的完成块(无论是否授予),并且我做到了,所以它会在完成块中返回到您的视图控制器中,但不适用于 iOS 9 及更低版本,您需要特殊处理:

// MARK: - Actions
@IBAction func notificationButton(_ sender: UIButton) 

    let myApplication = UIApplication.shared.delegate as! AppDelegate
    myApplication.registerAPNSServicesForApplication(UIApplication.shared)  (granted) -> (Void) in

        if #available(iOS 10.0, *) 

            if granted 

            else 

            

        else 

            // will not be returned because iOS 9 has no completion block for granting the permission it will require special way.

        

    


说实话,我没有 iOS 9 的设备来模拟完成块,但我认为根据Apple Analytics for November 2017Apple Analytics for November 2017,我认为 iOS 9 及以下的用户只有 10%

应该这样做:)

【讨论】:

不,一天都想不通,所以谢谢 ;) 嘿!你的回答很好,我也遇到了同样的问题。但是,当用户做出选择时,我希望你推送一个 ViewController。你知道我该怎么做吗@Aaoli? @KevinB 嘿,将其添加到已授予的块中,但仅适用于 iOS 10 及更高版本。 @AaoIi 我就是这么写的,但什么也没发生:/ @KevinB 可以告诉我你是怎么做到的吗?

以上是关于Firebase iOS 11 在按钮按下后要求用户通知的主要内容,如果未能解决你的问题,请参考以下文章

Kivy - 按下后更改按钮的颜色?

替换两个不同的片段后,按下后​​退按钮时会重新创建第一个片段

大神们,求救啊,用delphi7做

C++MFC编程在工具栏中添加按钮,按下后没有反应,怎么回事

登录按钮按下后,如何获取Tkinter entry的值并传递给SQL查询?

按下返回按钮后,listview会隐藏UI IOS