如何在 Swift 中设置推送通知

Posted

技术标签:

【中文标题】如何在 Swift 中设置推送通知【英文标题】:How to set up push notifications in Swift 【发布时间】:2014-07-22 22:59:44 【问题描述】:

我正在尝试为我的应用程序设置推送通知系统。我有一个服务器和一个开发者许可证来设置推送通知服务。

我目前正在 Swift 中运行我的应用程序。我希望能够从我的服务器远程发送通知。我该怎么做?

【问题讨论】:

【参考方案1】:

斯威夫特 2:

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

【讨论】:

没有收到委托回叫...我已经尝试了所有可能的解决方案:网络正常,所有端口都打开,证书和配置文件正常,App ID 支持推送通知和推送功能通知已开启……最奇怪的是,相同的代码 sn-p 在 Objective-c 项目中运行良好(使用相同的证书、配置文件和互联网连接)……【参考方案2】:

虽然处理推送通知的答案很好,但我仍然相信立即分享集成的完整案例以缓解:

为APNS注册应用程序,(在AppDelegate.swift中的didFinishLaunchingWithOptions方法中包含以下代码)


IOS 9

var settings : UIUserNotificationSettings = UIUserNotificationSettings(forTypes:UIUserNotificationType.Alert|UIUserNotificationType.Sound, categories: nil)
UIApplication.sharedApplication().registerUserNotificationSettings(settings)
UIApplication.sharedApplication().registerForRemoteNotifications()

IOS 10 之后

引入 UserNotifications 框架:

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


注册申请APNS

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

    // If granted comes true you can enabled features based on authorization.
    guard granted else  return 

    application.registerForRemoteNotifications()

这将调用以下委托方法

func application(application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData) 
//send this device token to server


//Called if unable to register for APNS.
func application(application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: NSError) 

println(error)


收到通知后,代表将致电:

func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) 

    println("Recived: \(userInfo)")
   //Parsing userinfo:
   var temp : NSDictionary = userInfo
   if let info = userInfo["aps"] as? Dictionary<String, AnyObject> 
            
                var alertMsg = info["alert"] as! String
                var alert: UIAlertView!
                alert = UIAlertView(title: "", message: alertMsg, delegate: nil, cancelButtonTitle: "OK")
                alert.show()
            

要确定我们可以使用的权限:

UNUserNotificationCenter.current().getNotificationSettings() (setttings) in

        switch setttings.soundSetting
        case .enabled:
            print("enabled sound")

        case .disabled:
            print("not allowed notifications")

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

那么 APNS 的清单:

使用推送通知创建 AppId 允许 使用有效的证书和应用 ID 创建 SSL 证书 创建具有相同证书的配置文件,并确保添加设备以防沙箱(开发配置)

注意:如果在 SSL 证书之后创建配置文件会很好。

带代码:

为推送通知注册应用程序 处理 didRegisterForRemoteNotificationsWithDeviceToken 方法 设置目标>能力>后台模式>远程通知 处理 didReceiveRemoteNotification

【讨论】:

谢谢!它特别有助于解析用户信息。 UIAlertView 已弃用。改为使用 UIAlertController 和 UIAlertControllerStyleAlert 的preferredStyle。 您能否编辑您的答案,并展示如何使用 UIAlertController 自定义声音? @XcodeNOOB : 准确分享,你在找什么? @Arvind 我正在尝试显示与默认声音不同的警报。声音将来自 ios 系统中的库/声音。但无论我做什么,我都会得到默认声音(我知道可以从服务器端更改它,但我想从设备更改它,因为用户可以选择自己的声音)。现在在您的代码中,我可以看到您创建了 UIAlertView,如果您也可以共享代码以对其进行自定义,这样当警报出现时会听到不同的声音,那就太好了。【参考方案3】:

要注册通过 Apple 推送服务接收推送通知,您必须调用 UIApplicationregisterForRemoteNotifications() 方法。

如果注册成功,应用程序会调用您的应用程序委托对象的application:didRegisterForRemoteNotificationsWithDeviceToken: 方法并将设备令牌传递给它。

您应该将此令牌传递给您用来为设备生成推送通知的服务器。如果注册失败,则应用调用其应用代理的application:didFailToRegisterForRemoteNotificationsWithError: 方法。

查看Local and Push Notification Programming Guide。

【讨论】:

registerForRemoteNotifications()只能从iOS 8获得,iOS 7应该用什么? @JoshHarington iOS 7 不是在 Swift 之前发布的吗? @11684 Swift 通过在应用程序中捆绑标准库来支持 iOS 7。 记得在 Target Settings -> Capabilities 中切换 ON Push Notifications 你为什么要用iOS7??【参考方案4】:

registerForRemoteNotification() 已从 ios8 中删除。

所以你应该使用UIUserNotification

代码示例:

var type = UIUserNotificationType.Badge | UIUserNotificationType.Alert | UIUserNotificationType.Sound;
var setting = UIUserNotificationSettings(forTypes: type, categories: nil);
UIApplication.sharedApplication().registerUserNotificationSettings(setting);
UIApplication.sharedApplication().registerForRemoteNotifications();

希望这会对你有所帮助。

【讨论】:

不要忘记这仅适用于 iOS 8+。如果您还想支持 iOS 7,请参阅***.com/a/28742391/131183 仅供参考,这不再适用于 Swift 2。对于 Swift 2,请参阅下面的 @AdamWaite 答案【参考方案5】:

要支持 ios 8 及之前版本,请使用:

// Register for Push Notitications, if running iOS 8
if application.respondsToSelector("registerUserNotificationSettings:") 

  let types:UIUserNotificationType = (.Alert | .Badge | .Sound)
  let settings:UIUserNotificationSettings = UIUserNotificationSettings(forTypes: types, categories: nil)

  application.registerUserNotificationSettings(settings)
  application.registerForRemoteNotifications()

 else       
  // Register for Push Notifications before iOS 8
  application.registerForRemoteNotificationTypes(.Alert | .Badge | .Sound)

【讨论】:

【参考方案6】:

斯威夫特 4

我认为这是iOS 8 及以上设置的正确方法

Capabilities 选项卡中打开Push Notifications

导入UserNotifications

import UserNotifications

修改didFinishLaunchingWithOptions

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool 


    if let notification = launchOptions?[.remoteNotification] as? [String: AnyObject] 

        // If your app wasn’t running and the user launches it by tapping the push notification, the push notification is passed to your app in the launchOptions

        let aps = notification["aps"] as! [String: AnyObject]
        UIApplication.shared.applicationIconBadgeNumber = 0
    

    registerForPushNotifications()

    return true

每次启动应用时都致电registerUserNotificationSettings(_:) 非常重要。这是因为用户可以随时进入“设置”应用并更改通知权限。 application(_:didRegisterUserNotificationSettings:) 将始终为您提供用户当前对您的应用允许的权限。

复制粘贴这个AppDelegate扩展

// Push Notificaion
extension AppDelegate 
func registerForPushNotifications() 
    if #available(iOS 10.0, *) 
        UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) 
            [weak self] (granted, error) in
            print("Permission granted: \(granted)")

            guard granted else 
                print("Please enable \"Notifications\" from App Settings.")
                self?.showPermissionAlert()
                return
            

            self?.getNotificationSettings()
        
     else 
        let settings = UIUserNotificationSettings(types: [.alert, .sound, .badge], categories: nil)
        UIApplication.shared.registerUserNotificationSettings(settings)
        UIApplication.shared.registerForRemoteNotifications()
    


@available(iOS 10.0, *)
func getNotificationSettings() 

    UNUserNotificationCenter.current().getNotificationSettings  (settings) in
        print("Notification settings: \(settings)")
        guard settings.authorizationStatus == .authorized else  return 
        DispatchQueue.main.async 
            UIApplication.shared.registerForRemoteNotifications()
        
    


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

    let tokenParts = deviceToken.map  data -> String in
        return String(format: "%02.2hhx", data)
    

    let token = tokenParts.joined()
    print("Device Token: \(token)")
    //UserDefaults.standard.set(token, forKey: DEVICE_TOKEN)


func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) 
    print("Failed to register: \(error)")


func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable: Any]) 

    // If your app was running and in the foreground
    // Or
    // If your app was running or suspended in the background and the user brings it to the foreground by tapping the push notification

    print("didReceiveRemoteNotification /(userInfo)")

    guard let dict = userInfo["aps"]  as? [String: Any], let msg = dict ["alert"] as? String else 
        print("Notification Parsing Error")
        return
    


func showPermissionAlert() 
    let alert = UIAlertController(title: "WARNING", message: "Please enable access to Notifications in the Settings app.", preferredStyle: .alert)

    let settingsAction = UIAlertAction(title: "Settings", style: .default) [weak self] (alertAction) in
        self?.gotoAppSettings()
    

    let cancelAction = UIAlertAction(title: "Cancel", style: .default, handler: nil)

    alert.addAction(settingsAction)
    alert.addAction(cancelAction)

    DispatchQueue.main.async 
        self.window?.rootViewController?.present(alert, animated: true, completion: nil)
    


private func gotoAppSettings() 

    guard let settingsUrl = URL(string: UIApplicationOpenSettingsURLString) else 
        return
    

    if UIApplication.shared.canOpenURL(settingsUrl) 
        UIApplication.shared.openURL(settingsUrl)
    


签出:Push Notifications Tutorial: Getting Started

【讨论】:

application:didFailToRegisterForRemoteNotificationsWithError 在用户拒绝或存在其他网络错误或两者兼有时调用? show(alert: alert) 和 registerForPushNotifications(application) 在您的代码中有问题 当我将您的应用程序复制到我的应用程序委托类时,我会收到这些错误 使用未解析的标识符“show”和传递给的参数不带参数的调用 在这个问题上需要帮助:- ***.com/questions/52676650/…【参考方案7】:

感谢之前的回答。 Xcode 进行了一些更改,以下是通过 XCode 7 代码检查并支持 iOS 7 及更高版本的 SWIFT 2 代码:

    if #available(iOS 8.0, *) 
        let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
        UIApplication.sharedApplication().registerUserNotificationSettings(settings)
        UIApplication.sharedApplication().registerForRemoteNotifications()
     else 
        let settings = UIRemoteNotificationType.Alert.union(UIRemoteNotificationType.Badge).union(UIRemoteNotificationType.Sound)
        UIApplication.sharedApplication().registerForRemoteNotificationTypes(settings)
    

【讨论】:

【参考方案8】:

斯威夫特 4

导入UserNotifications框架,在AppDelegate中添加UNUserNotificationCenterDelegate

import UserNotifications

class AppDelegate: UIResponder, UIApplicationDelegate, UNUserNotificationCenterDelegate

为APNS注册应用程序,(在AppDelegate.swift中的didFinishLaunchingWithOptions方法中包含以下代码)

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

这将调用以下委托方法

func application(_ application: UIApplication,didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) 
    //send this device token to server



//Called if unable to register for APNS.
func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) 
    print(error)

收到通知后,代表将致电:

private func application(application: UIApplication, didReceiveRemoteNotification userInfo: [NSObject : AnyObject]) 

    print("Recived: \(userInfo)")
    //Parsing userinfo:


【讨论】:

【参考方案9】:

斯威夫特 3:

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

确保在视图控制器的顶部导入 UserNotifications

import UserNotifications

【讨论】:

【参考方案10】:

您可以使用以下代码 sn-p 发送通知:

let settings = UIUserNotificationSettings(forTypes: [.Alert, .Badge, .Sound], categories: nil)
if(UIApplication.sharedApplication().currentUserNotificationSettings() == settings )
//OK
else
//KO

【讨论】:

【参考方案11】:

我在 AppDelegate.swift 中使用这个代码片段:

let pushType = UIUserNotificationType.alert.union(.badge).union(.sound)
let pushSettings = UIUserNotificationSettings(types: pushType
            , categories: nil)

application.registerUserNotificationSettings(pushSettings)
application.registerForRemoteNotifications()

【讨论】:

【参考方案12】:

100% 工作中... 您可以正确读取一个信号文档并进行设置https://documentation.onesignal.com/docs/ios-sdk-setup OneSignal 下面的代码导入 AppDelegate

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool 
    // Override point for customization after application launch.
    OneSignal.setLogLevel(.LL_VERBOSE, visualLevel: .LL_NONE)
    
    // OneSignal initialization
    let onesignalInitSettings = [kOSSettingsKeyAutoPrompt: false, kOSSettingsKeyInAppLaunchURL: false]
    
    OneSignal.initWithLaunchOptions(launchOptions,
                                    appId: "YOUR_ONE_SIGNAL_ID",
                                    handleNotificationAction: nil,
                                    settings: onesignalInitSettings)
    
    OneSignal.inFocusDisplayType = OSNotificationDisplayType.inAppAlert;
    // promptForPushNotifications will show the native iOS notification permission prompt.
    // We recommend removing the following code and instead using an In-App Message to prompt for notification permission (See step 8)
    OneSignal.promptForPushNotifications(userResponse:  accepted in
        print("User accepted notifications: \(accepted)")
    )

    return true

【讨论】:

以上是关于如何在 Swift 中设置推送通知的主要内容,如果未能解决你的问题,请参考以下文章

XCUITest - 如何访问 XCUITest 中的应用设备令牌以触发推送通知,但无需在应用代码中设置任何 UIView?

在 Swift 中推送 iOS8 的通知状态

iOS Swift App 不会收到 Parse Server 发送的推送通知

为啥我在 Swift 中没有收到来自 Firebase 的推送通知?

使用 NodeJS 对 Google 推送通知的操作

如何在 AppDelegate 之外注册推送通知?