Регистрация для 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()
Ошибка, которую я получаю, это "Ярлыки аргументов" (forTypes:, categories:) "не соответствуют никаким доступным перегрузкам"
Есть ли другая команда, с которой я мог бы попытаться это сделать?
Ответы
Ответ 1
Импортируйте структуру UserNotifications
и добавьте UNUserNotificationCenterDelegate
в AppDelegate.swift
Запросить разрешение пользователя
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("", {$0 + String(format: "%02X", $1)})
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")
}
}
Ответ 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
У меня возникли проблемы с ответами здесь на то, чтобы преобразовать объект deviceToken Data в строку для отправки на мой сервер с текущей бета-версией Xcode 8. Особенно тот, который использовал deviceToken.description как в 8.0b6, который вернул бы "32 Байты", что не очень полезно:)
Это то, что сработало для меня...
Создайте расширение для Data для реализации метода 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...
}
Ответ 4
import UserNotifications
Затем перейдите в редактор проекта для вашей цели и на вкладке General найдите раздел Linked Frameworkworks and Libraries.
Нажмите + и выберите 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])
}
Используйте методы делегата уведомления
// 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)")
}
Для получения 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
Ответ 5
В iOS10 вместо вашего кода вы должны запросить авторизацию для уведомления со следующим: (Не забудьте добавить UserNotifications
Framework)
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
)
Ответ 6
Хорошо, эта работа для меня.
Сначала в 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("", {$0 + String(format: "%02X", $1)})
}
Ответ 7
Голова, вы должны использовать основной поток для этого действия.
let center = UNUserNotificationCenter.current()
center.requestAuthorization(options:[.badge, .alert, .sound]) { (granted, error) in
if granted {
DispatchQueue.main.async(execute: {
UIApplication.shared.registerForRemoteNotifications()
})
}
}
Ответ 8
Во-первых, прослушайте статус уведомления пользователя, то есть registerForRemoteNotifications()
чтобы получить токен APNs устройства;
Во-вторых, авторизация запроса. При авторизации пользователем устройствоToken будет отправлено слушателю, 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) {
//
}
}
Ответ 9
Ответ от 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 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
Просто сделайте следующее в didFinishWithLaunching:
:
if #available(iOS 10.0, *) {
let center = UNUserNotificationCenter.current()
center.delegate = self
center.requestAuthorization(options: []) { _, _ in
application.registerForRemoteNotifications()
}
}
Помните об операторе импорта:
import UserNotifications
Ответ 11
@Team,
Я создал один пример приложения, которое используется для запроса разрешения уведомления пользователем. Репо также проверьте, что если пользователю отказано в разрешении, оно будет отображать предупреждение, как будто нам нужно ваше разрешение на уведомление.
NotificationPermission
Примечание. Прямо сейчас каждый раз, когда снова используется приложение, запрашивается "Нам нужно разрешение на уведомление", и если пользователь не разрешает разрешение. Вы можете изменить частоту повторного запроса разрешения в соответствии с требованиями, такими как приложение whats и другие приложения.
Ответ 12
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
}
Ответ 13
Взгляните на этот комментарий:
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)")
}
}
Дайте мне знать, если есть какие-либо проблемы!
Ответ 14
Вот код в Swift 4.1 и Xcode 9.3
- Включение Push-уведомлений - просто перейдите в редактор проекта для своей цели, а затем нажмите вкладку "Возможности". Найдите Push-уведомления и переключите его значение на ON.
-
В iOS 10 была введена новая структура под названием UserNotifications и должна быть импортирована для доступа к классу UNUserNotificationCenter. Добавьте следующий оператор импорта в начало AppDelegate.swift
import UserNotifications
Затем перейдите к редактору проекта для своей цели, а на вкладке "Общие" найдите раздел "Связанные структуры и библиотеки".
Нажмите + и выберите UserNotifications.framework
Пользователь выполнил следующие методы регистрации и обработки APNS
//MARK: - Remote Notificaton
extension AppDelegate: UNUserNotificationCenterDelegate {
func registerForPushNotifications(application: UIApplication) {
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().requestAuthorization(options: [.badge, .sound, .alert], completionHandler: { (granted, _) in
if granted {
UIApplication.shared.registerForRemoteNotifications()
} else { }
})
} else {
let notificationSettings = UIUserNotificationSettings(
types: [.badge, .sound, .alert], categories: nil)
UIApplication.shared.registerUserNotificationSettings(notificationSettings)
}
}
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
let deviceToken = deviceToken.hexString()
Debug.Log(message: "Device Token - \(deviceToken.hexString())")
}
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
Debug.Log(message: "Failed to register for RemoteNotifications")
}
@available(iOS 10.0, *)
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
//Handle the notification
if UIApplication.shared.applicationState == .inactive {
let seconds = 1.0
let delay = seconds * Double(NSEC_PER_SEC) // nanoseconds per seconds
let dispatchTime = DispatchTime.now() + Double(Int64(delay)) / Double(NSEC_PER_SEC)
DispatchQueue.main.asyncAfter(deadline: dispatchTime, execute: {
self.handlerRemoteNotification(response.notification.request.content.userInfo)
})
} else {
handlerRemoteNotification(response.notification.request.content.userInfo)
}
}
func handlerRemoteNotification(_ userInfo: [AnyHashable: Any]) {
if #available(iOS 10.0, *) {
} else {
if UIApplication.shared.applicationState != .active { return }
}
if let jsonString: String = userInfo["parameters"] as? String {
let data = jsonString.data(using: String.Encoding.utf8, allowLossyConversion: false)!
do {
let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: AnyObject]
if let json = json {
// handle Json
}
} catch let error as NSError {
Debug.Log(message: "Failed to load: \(error.localizedDescription)")
}
}
}
func application( _ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any], fetchCompletionHandler handler: @escaping (UIBackgroundFetchResult) -> Void) {
if UIApplication.shared.applicationState != .active {
if let cId = userInfo["Number"] as? Int64 {
// Push your ViewController
}
} else {
}
}
}
// Here extension for data
extension Data {
func hexString() -> String {
return self.reduce("") { string, byte in
string + String(format: "%02X", byte)
}
}
}