Регистрация для Push-уведомлений в Xcode 8 / Swift 3.0?
Я пытаюсь заставить мое приложение работать в Xcode 8.0, и я столкнулся с ошибкой. Я знаю, что этот код отлично работал в предыдущих версиях swift, но я предполагаю, что код для этого изменен в новой версии. Вот код, который я пытаюсь запустить:
let settings = UIUserNotificationSettings(forTypes: [.Sound, .Alert, .Badge], categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.shared().registerForRemoteNotifications()
ошибки, которые я получаю-это "ярлыки аргумент '(объекта можно, по категориям:)' не соответствует никаким существующим перегрузок"
есть ли другая команда, которую я мог бы попытаться заставить это работать?
12 ответов:
импорт
UserNotifications
рамки и добавитьUNUserNotificationCenterDelegate
в AppDelegate.Свифтзапросить разрешение пользователя
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 }
получение маркера устройства
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let deviceTokenString = deviceToken.reduce("", { + String(format: "%02X", )}) print(deviceTokenString) }
в случае ошибки
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) { print("i am not available in simulator \(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") } }
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 }
у меня были проблемы с ответами здесь при преобразовании объекта данных deviceToken в строку для отправки на мой сервер с текущей бета-версией Xcode 8. Особенно тот, который использовал deviceToken.описание как в 8. 0b6, что бы вернуть "32 байта", что не очень полезно :)
это то, что работал для меня...
создайте расширение для данных, чтобы реализовать метод "hexString":
extension Data { func hexString() -> String { return self.reduce("") { string, byte in string + String(format: "%02X", byte) } } }
а затем использовать это, когда вы получаете обратный вызов от регистрации для удаленных уведомлений:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let deviceTokenString = deviceToken.hexString() // Send to your server here... }
в iOS10 вместо вашего кода Вы должны запросить авторизацию для уведомления со следующим: (Не забудьте добавить
UserNotifications
основы)if #available(iOS 10.0, *) { UNUserNotificationCenter.current().requestAuthorization([.alert, .sound, .badge]) { (granted: Bool, error: NSError?) in // Do something here } }
кроме того, правильный код для вас (используйте в
else
предыдущего условия, например):let setting = UIUserNotificationSettings(types: [.alert, .badge, .sound], categories: nil) UIApplication.shared().registerUserNotificationSettings(setting) UIApplication.shared().registerForRemoteNotifications()
наконец, убедится
Push Notification
активируется подtarget
->Capabilities
->Push notification
. (установите его наOn
)
import UserNotifications
затем перейдите в Редактор проектов для вашей цели и на вкладке Общие найдите раздел Связанные фреймворки и библиотеки.
нажмите + и выберите UserNotifications.рамки:
// 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]) }
использовать методы делегирования уведомлений
// 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("", { + 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)") }
для получения push-уведомлений
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { completionHandler(UIBackgroundFetchResult.noData) }
настройка push-уведомлений позволяет использовать эту функцию в Xcode 8 для вашего приложения. Просто перейти в редактор проекта для вашей цели и затем нажмите на кнопку функции. Ищите Push-Уведомления и тумблер его значение ON.
Проверьте ссылку ниже для получения дополнительных методов делегирования уведомлений
обработка локальных и удаленных уведомлений UIApplicationDelegate -обработка локальных и удаленных уведомлений
https://developer.apple.com/reference/uikit/uiapplicationdelegate
Ну это работа для меня. Первый в AppDelegate
import UserNotifications
затем:
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() } }
чтобы получить devicetoken:
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) { let deviceTokenString = deviceToken.reduce("", { + String(format: "%02X", )}) }
Heads up, вы должны использовать основной поток для этого действия.
let center = UNUserNotificationCenter.current() center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in if granted { DispatchQueue.main.async(execute: { UIApplication.shared.registerForRemoteNotifications() }) } }
первый, слушайте статус уведомления пользователя, т. е.,
registerForRemoteNotifications()
чтобы получить маркер устройства APNs;
второй запрос авторизации. Когда будучи авторизованным пользователем, завершен будет направлен на слушателя,AppDelegate
;
третий, сообщите маркер устройства на ваш сервер.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) { // } }
ответ от ast1 очень просто и полезно. Это работает для меня, спасибо. Я просто хочу вытащить его здесь, чтобы люди, которым нужен этот ответ, могли легко найти его. Итак, вот мой код от регистрации локального и удаленного (push) уведомления.
//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 }
просто сделайте следующее в
didFinishWithLaunching:
:if #available(iOS 10.0, *) { let center = UNUserNotificationCenter.current() center.delegate = self center.requestAuthorization(options: []) { _, _ in application.registerForRemoteNotifications() } }
помните об операторе import:
import UserNotifications
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { let notificationCenter = UNUserNotificationCenter.current() notificationCenter.requestAuthorization([.alert , .sound]) { (finished, err) in if err == nil { application.registerForRemoteNotifications() } } return true }
взгляните на этот закомментированный код:
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: []) }.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)") } }
Дайте мне знать, если есть какие-либо проблемы!