ios 在 Xcode 8/Swift 3.0 中注册推送通知?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/37956482/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 09:30:29  来源:igfitidea点击:

Registering for Push Notifications in Xcode 8/Swift 3.0?

iospush-notificationswift3ios10unusernotificationcenter

提问by Asher Hawthorne

I'm trying to get my app working in Xcode 8.0, and am running into an error. I know this code worked fine in previous versions of swift, but I'm assuming the code for this is changed in the new version. Here's the code I'm trying to run:

我正在尝试让我的应用程序在Xcode 8.0 中运行,但遇到了错误。我知道这段代码在以前版本的 swift 中运行良好,但我假设在新版本中更改了此代码。这是我试图运行的代码:

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

The error that I'm getting is "Argument labels '(forTypes:, categories:)' do not match any available overloads"

我得到的错误是“参数标签 '(forTypes:, Categories:)' 与任何可用的重载不匹配”

Is there a different command that I could try to get this working?

是否有不同的命令可以尝试使其正常工作?

回答by Anish Parajuli ?

Import the UserNotificationsframework and add the UNUserNotificationCenterDelegatein AppDelegate.swift

导入UserNotifications框架并UNUserNotificationCenterDelegate在 AppDelegate.swift 中添加

Request user permission

请求用户权限

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {


        let center = UNUserNotificationCenter.current()
        center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
            // Enable or disable features based on authorization.
        }
        application.registerForRemoteNotifications()
        return true
}

Getting device token

获取设备令牌

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

    let deviceTokenString = deviceToken.reduce("", {
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {

        print("i am not available in simulator \(error)")
}
+ String(format: "%02X", )}) print(deviceTokenString) }

In case of error

出错时

UNUserNotificationCenter.current().getNotificationSettings(){ (settings) in

            switch settings.soundSetting{
            case .enabled:

                print("enabled sound setting")

            case .disabled:

                print("setting has been disabled")

            case .notSupported:
                print("something vital went wrong here")
            }
        }

In case if you need to know the permissions granted

如果您需要知道授予的权限

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    if #available(iOS 10, *) {

        //Notifications get posted to the function (delegate):  func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: () -> Void)"


        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in

            guard error == nil else {
                //Display Error.. Handle Error.. etc..
                return
            }

            if granted {
                //Do stuff here..

                //Register for RemoteNotifications. Your Remote Notifications can display alerts now :)
                DispatchQueue.main.async {
                    application.registerForRemoteNotifications()
                }
            }
            else {
                //Handle user denying permissions..
            }
        }

        //Register for remote notifications.. If permission above is NOT granted, all notifications are delivered silently to AppDelegate.
        application.registerForRemoteNotifications()
    }
    else {
        let settings = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
        application.registerUserNotificationSettings(settings)
        application.registerForRemoteNotifications()
    }

    return true
}

回答by Brandon

import UserNotifications  

回答by Mohamed Jaleel Nazir

// iOS 12 support
if #available(iOS 12, *) {  
    UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound, .provisional, .providesAppNotificationSettings, .criticalAlert]){ (granted, error) in }
    application.registerForRemoteNotifications()
}

// iOS 10 support
if #available(iOS 10, *) {  
    UNUserNotificationCenter.current().requestAuthorization(options:[.badge, .alert, .sound]){ (granted, error) in }
    application.registerForRemoteNotifications()
}
// iOS 9 support
else if #available(iOS 9, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 8 support
else if #available(iOS 8, *) {  
    UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil))
    UIApplication.shared.registerForRemoteNotifications()
}
// iOS 7 support
else {  
    application.registerForRemoteNotifications(matching: [.badge, .sound, .alert])
}

Next, go to the project editor for your target, and in the General tab, look for the Linked Frameworks and Libraries section.

接下来,转到目标的项目编辑器,并在 General 选项卡中查找 Linked Frameworks and Libraries 部分。

Click + and select UserNotifications.framework:

单击 + 并选择 UserNotifications.framework:

// Called when APNs has assigned the device a unique token
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {  
    // Convert token to string
    let deviceTokenString = deviceToken.reduce("", {
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    completionHandler(UIBackgroundFetchResult.noData)
}
+ String(format: "%02X", )}) print("APNs device token: \(deviceTokenString)") } // Called when APNs failed to register the device for push notifications func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { // Print the error to console (you should alert the user that registration failed) print("APNs registration failed: \(error)") }

Use Notification delegate methods

使用通知委托方法

extension Data {
    func hexString() -> String {
        return self.reduce("") { string, byte in
            string + String(format: "%02X", byte)
        }
    }
}

For receiving push notification

用于接收推送通知

func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let deviceTokenString = deviceToken.hexString()
    // Send to your server here...
}

Setting up push notifications is enabling the feature within Xcode 8 for your app. Simply go to the project editor for your targetand then click on the Capabilities tab. Look for Push Notificationsand toggle its value to ON.

设置推送通知是在 Xcode 8 中为您的应用启用该功能。只需转到目标的项目编辑器,然后单击Capabilities 选项卡。查找Push Notifications并将其值切换为ON

Check below link for more Notification delegate methods

检查以下链接以获取更多通知委托方法

Handling Local and Remote Notifications UIApplicationDelegate- Handling Local and Remote Notifications

https://developer.apple.com/reference/uikit/uiapplicationdelegate

处理本地和远程通知UIApplicationDelegate-处理本地和远程通知

https://developer.apple.com/reference/uikit/uiapplicationdelegate

回答by tomwilson

I had issues with the answers here in converting the deviceToken Data object to a string to send to my server with the current beta of Xcode 8. Especially the one that was using deviceToken.description as in 8.0b6 that would return "32 Bytes" which isn't very useful :)

我在将 deviceToken Data 对象转换为字符串以使用 Xcode 8 的当前测试版发送到我的服务器时遇到了答案问题。尤其是在 8.0b6 中使用 deviceToken.description 的那个会返回“32 字节”不是很有用:)

This is what worked for me...

这对我有用...

Create an extension on Data to implement a "hexString" method:

在 Data 上创建扩展以实现“hexString”方法:

if #available(iOS 10.0, *) {
        UNUserNotificationCenter.current().requestAuthorization([.alert, .sound, .badge]) { (granted: Bool, error: NSError?) in
            // Do something here
        }
    }

And then use that when you receive the callback from registering for remote notifications:

然后在收到注册远程通知的回调时使用它:

let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared().registerUserNotificationSettings(setting)
UIApplication.shared().registerForRemoteNotifications()

回答by tsnkff

In iOS10 instead of your code, you should request an authorization for notification with the following: (Don't forget to add the UserNotificationsFramework)

在 iOS10 而不是您的代码中,您应该使用以下内容请求通知授权:(不要忘记添加UserNotifications框架)

import UserNotifications

Also, the correct code for you is (use in the elseof the previous condition, for example):

此外,您的正确代码是(else例如,在前一个条件中使用):

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

    func registerForRemoteNotification() {
        if #available(iOS 10.0, *) {
            let center  = UNUserNotificationCenter.current()
            center.delegate = self
            center.requestAuthorization(options: [.sound, .alert, .badge]) { (granted, error) in
                if error == nil{
                    UIApplication.shared.registerForRemoteNotifications()
                }
            }
        }
        else {
            UIApplication.shared.registerUserNotificationSettings(UIUserNotificationSettings(types: [.sound, .alert, .badge], categories: nil))
            UIApplication.shared.registerForRemoteNotifications()
        }
    }

Finally, make sure Push Notificationis activated under target-> Capabilities-> Push notification. (set it on On)

最后,确保Push Notificationtarget-> Capabilities->下激活Push notification。(设置它On

回答by GoIn Su

Well this work for me. First in AppDelegate

嗯,这对我有用。AppDelegate 中的第一个

  func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {

       let deviceTokenString = deviceToken.reduce("", {
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
        if granted {
            DispatchQueue.main.async(execute: {
                UIApplication.shared.registerForRemoteNotifications()
            })
        }
    }
+ String(format: "%02X", )}) }

Then:

然后:

extension AppDelegate {
    /// 1. 监听 deviceToken
    UIApplication.shared.registerForRemoteNotifications()

    /// 2. 向操作系统索要推送权限(并获取推送 token)
    static func registerRemoteNotifications() {
        if #available(iOS 10, *) {
            let uc = UNUserNotificationCenter.current()
            uc.delegate = UIApplication.shared.delegate as? AppDelegate
            uc.requestAuthorization(options: [.alert, .badge, .sound]) { (granted, error) in
                if let error = error { // 无论是拒绝推送,还是不提供 aps-certificate,此 error 始终为 nil
                    print("UNUserNotificationCenter 注册通知失败, \(error)")
                }
                DispatchQueue.main.async {
                    onAuthorization(granted: granted)
                }
            }
        } else {
            let app = UIApplication.shared
            app.registerUserNotificationSettings(UIUserNotificationSettings(types: [.badge, .sound, .alert], categories: nil)) // 获取用户授权
        }
    }

    // 在 app.registerUserNotificationSettings() 之后收到用户接受或拒绝及默拒后,此委托方法被调用
    func application(_ app: UIApplication, didRegister notificationSettings: UIUserNotificationSettings) {
        // 已申请推送权限,所作的检测才有效
        // a 征询推送许可时,用户把app切到后台,就等价于默拒了推送
        // b 在系统设置里打开推送,但关掉所有形式的提醒,等价于拒绝推送,得不token,也收不推送
        // c 关掉badge, alert和sound 时,notificationSettings.types.rawValue 等于 0 和 app.isRegisteredForRemoteNotifications 成立,但能得到token,也能收到推送(锁屏和通知中心也能看到推送),这说明types涵盖并不全面
        // 对于模拟器来说,由于不能接收推送,所以 isRegisteredForRemoteNotifications 始终为 false
       onAuthorization(granted: app.isRegisteredForRemoteNotifications)
    }

    static func onAuthorization(granted: Bool) {
        guard granted else { return }
        // do something
    }
}

extension AppDelegate {
    func application(_ app: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        //
    }

    // 模拟器得不到 token,没配置 aps-certificate 的项目也得不到 token,网络原因也可能导致得不到 token
    func application(_ app: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
        //
    }
}

To get devicetoken:

获取设备令牌:

if #available(iOS 10.0, *) {

    let center = UNUserNotificationCenter.current()

    center.delegate = self
    center.requestAuthorization(options: []) { _, _ in
        application.registerForRemoteNotifications()
    }
}

回答by Mavrick Laakso

Heads up, you should be using the main thread for this action.

注意,您应该使用主线程执行此操作。

import UserNotifications

回答by DawnSong

First, listen to user notification status, i.e., registerForRemoteNotifications()to get APNs device token;
Second, request authorization. When being authorized by the user, deviceToken will be sent to the listener, the AppDelegate;
Third, report the device token to your server.

首先,监听用户通知状态,即registerForRemoteNotifications()获取APNs设备令牌;
第二,请求授权。当被用户授权时,deviceToken 会被发送给监听器AppDelegate
第三,将设备令牌报告给您的服务器。

    //1. In Appdelegate: didFinishLaunchingWithOptions add these line of codes
    let mynotif = UNUserNotificationCenter.current()
    mynotif.requestAuthorization(options: [.alert, .sound, .badge]) {(granted, error) in }//register and ask user's permission for local notification

    //2. Add these functions at the bottom of your AppDelegate before the last "}"
    func application(_ application: UIApplication, didRegister notificationSettings: UNNotificationSettings) {
        application.registerForRemoteNotifications()//register for push notif after users granted their permission for showing notification
}
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    let tokenString = deviceToken.reduce("", {##代码## + String(format: "%02X", )})
    print("Device Token: \(tokenString)")//print device token in debugger console
}
    func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    print("Failed to register: \(error)")//print error in debugger console
}

回答by Bart?omiej Semańczyk

Simply do the following in didFinishWithLaunching::

只需在 中执行以下操作didFinishWithLaunching:

##代码##

Remember about import statement:

记住导入语句:

##代码##

回答by Luthfi Rahman

The answer from ast1is very simple and useful. It works for me, thank you so much. I just want to poin it out here, so people who need this answer can find it easily. So, here is my code from registering local and remote (push) notification.

来自ast1的答案非常简单和有用。它对我有用,非常感谢。我只是想在这里指出来,以便需要这个答案的人可以轻松找到它。所以,这是我注册本地和远程(推送)通知的代码。

##代码##