可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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:
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\"
Is there a different command that I could try to get this working?
回答1:
Import the UserNotifications
framework and add the UNUserNotificationCenterDelegate
in 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(\"\", {$0 + String(format: \"%02X\", $1)})
print(deviceTokenString)
}
In case of error
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
print(\"i am not available in simulator \\(error)\")
}
In case if you need to know the permissions granted
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\")
}
}
回答2:
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
}
回答3:
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 :)
This is what worked for me...
Create an extension on Data to implement a \"hexString\" method:
extension Data {
func hexString() -> String {
return self.reduce(\"\") { string, byte in
string + String(format: \"%02X\", byte)
}
}
}
And then use that when you receive the callback from registering for remote notifications:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.hexString()
// Send to your server here...
}
回答4:
In iOS10 instead of your code, you should request an authorization for notification with the following: (Don\'t forget to add the UserNotifications
Framework)
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization([.alert, .sound, .badge]) { (granted: Bool, error: NSError?) in
// Do something here
}
}
Also, the correct code for you is (use in the else
of the previous condition, for example):
let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil)
UIApplication.shared().registerUserNotificationSettings(setting)
UIApplication.shared().registerForRemoteNotifications()
Finally, make sure Push Notification
is activated under target
-> Capabilities
-> Push notification
. (set it on On
)
回答5:
import UserNotifications
Next, go to the project editor for your target, and in the General tab, look for the Linked Frameworks and Libraries section.
Click + and select UserNotifications.framework:
// 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])
}
Use Notification delegate methods
// 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(\"\", {$0 + String(format: \"%02X\", $1)})
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)\")
}
For receiving push notification
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
completionHandler(UIBackgroundFetchResult.noData)
}
Setting up push notifications is enabling the feature within Xcode 8
for your app. Simply go to the project editor for your target and then
click on the Capabilities tab. Look for Push Notifications and toggle
its value to 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
回答6:
Well this work for me.
First in AppDelegate
import UserNotifications
Then:
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()
}
}
To get devicetoken:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceTokenString = deviceToken.reduce(\"\", {$0 + String(format: \"%02X\", $1)})
}
回答7:
Heads up, you should be using the main thread for this action.
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
if granted {
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
}
回答8:
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.
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) {
//
}
}
回答9:
The answer from ast1 is 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.
//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(\"\", {$0 + String(format: \"%02X\", $1)})
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
}
回答10:
Simply do the following in didFinishWithLaunching:
:
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: []) { _, _ in
application.registerForRemoteNotifications()
}
}
Remember about import statement:
import UserNotifications
回答11:
Take a look at this commented code:
import Foundation
import UserNotifications
import ObjectMapper
class AppDelegate{
let center = UNUserNotificationCenter.current()
}
extension AppDelegate {
struct Keys {
static let deviceToken = \"deviceToken\"
}
// MARK: - UIApplicationDelegate Methods
func application(_: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
if let tokenData: String = String(data: deviceToken, encoding: String.Encoding.utf8) {
debugPrint(\"Device Push Token \\(tokenData)\")
}
// Prepare the Device Token for Registration (remove spaces and < >)
setDeviceToken(deviceToken)
}
func application(_: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
debugPrint(error.localizedDescription)
}
// MARK: - Private Methods
/**
Register remote notification to send notifications
*/
func registerRemoteNotification() {
center.requestAuthorization(options: [.alert, .sound, .badge]) { (granted, error) in
// Enable or disable features based on authorization.
if granted == true {
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
} else {
debugPrint(\"User denied the permissions\")
}
}
}
/**
Deregister remote notification
*/
func deregisterRemoteNotification() {
UIApplication.shared.unregisterForRemoteNotifications()
}
func setDeviceToken(_ token: Data) {
let token = token.map { String(format: \"%02.2hhx\", arguments: [$0]) }.joined()
UserDefaults.setObject(token as AnyObject?, forKey: “deviceToken”)
}
class func deviceToken() -> String {
let deviceToken: String? = UserDefaults.objectForKey(“deviceToken”) as? String
if isObjectInitialized(deviceToken as AnyObject?) {
return deviceToken!
}
return \"123\"
}
func isObjectInitialized(_ value: AnyObject?) -> Bool {
guard let _ = value else {
return false
}
return true
}
}
extension AppDelegate: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: @escaping(UNNotificationPresentationOptions) -> Swift.Void) {
(\"\\(notification.request.content.userInfo) Identifier: \\(notification.request.identifier)\")
completionHandler([.alert, .badge, .sound])
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping() -> Swift.Void) {
debugPrint(\"\\(response.notification.request.content.userInfo) Identifier: \\(response.notification.request.identifier)\")
}
}
Let me know if there is any problem!