如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?
Posted
技术标签:
【中文标题】如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?【英文标题】:How can I register user's ios device for receiving push messages from place other than AppDelegate? 【发布时间】:2016-11-29 13:16:55 【问题描述】:目前在我的appDelegate
didFinishLaunchingWithOptions
中,我正在调用以下方法:
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
我在AppDelegate
中也实现了以下方法:
didRegisterForRemoteNotificationsWithDeviceToken
didFailToRegisterForRemoteNotificationsWithError
didReceiveRemoteNotification
当用户第一次启动我的应用程序时,他会看到一个弹出窗口,询问他是否允许接收推送消息。
我想推迟显示此弹出窗口,直到用户在“设置”菜单中手动选择特定选项。
在“设置”菜单中,我有一个 UISwitch
,每次用户更改它时我都会检查它的状态:
func messagesStateChanged(_ sender: UISwitch)
if(sender.isOn)
defaults.set("true", forKey: "popupMessages")
defaults.synchronize()
else
defaults.set("false", forKey: "popupMessages")
defaults.synchronize()
有没有办法将push
处理从应用程序委托移动到设置菜单,以便用户在启动应用程序后不会立即看到弹出窗口,而是在他选择UISwitch
时看到?另外 - 如果我将它移到 Settings 类,这是否适用于未来并且所有 push
功能都可以正常工作?
【问题讨论】:
为什么要让经过批准的标准化设计模式变得更糟? 【参考方案1】:您可以通过在您可以访问UIKit
的应用程序中的任何位置访问UIApplication.shared
类属性来访问didFinishLaunchingWithOptions
中提供给您的UIApplication
实例。我通常会创建一个管理通知的包装类,它允许您在以后编写单元测试时注入UIApplication
依赖项。
注册调用应该在您激活开关时发生:
func messagesStateChanged(_ sender: UISwitch)
if(sender.isOn)
defaults.set("true", forKey: "popupMessages")
defaults.synchronize()
let application = UIApplication.shared
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
else
defaults.set("false", forKey: "popupMessages")
defaults.synchronize()
我使用的简化包装类(为简单起见使用单例):
class NotificationManager
static var shared = NotificationManager()
private var application : UIApplication?
func setup(application: UIApplication)
self.application = application
func register ()
guard let application = application else
print("Attempt to register without calling setup")
return
let notificationTypes: UIUserNotificationType = [UIUserNotificationType.alert, UIUserNotificationType.badge, UIUserNotificationType.sound]
let pushNotificationSettings = UIUserNotificationSettings(types: notificationTypes, categories: nil)
application.registerUserNotificationSettings(pushNotificationSettings)
application.registerForRemoteNotifications()
这要求您在didFinishLaunchingMethod
中调用 setup:
NotificationManager.shared.setup(application: application)
但是,无论您需要在哪里注册通知:
func messagesStateChanged(_ sender: UISwitch)
if(sender.isOn)
...
NotificationManager.shared.register()
...
这使您可以稍后通过注入UIApplication
模拟对象轻松测试NotificationManager
类,并且该类还很好地封装了所有与通知相关的逻辑。通过一些修改,它可以轻松跟踪您是否已经注册,跟踪您收到的推送令牌,甚至处理 ios 8/9 向后兼容性,而无需复制样板代码。
【讨论】:
能否分享一下该包装类的示例代码? 你去。更多地将其用作一个想法,而不是直接使用此解决方案。 我在这里问了一个后续问题***.com/questions/41025023/…你能看一下吗?以上是关于如何注册用户的 ios 设备以接收来自 AppDelegate 以外的地方的推送消息?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 aws sns 中注册 iOS 设备令牌以接收推送通知?
如何注册 android 设备以通过 App Engine 后端接收推送通知?
实现推送通知服务器:如何检查传递设备令牌的消息是不是来自真实设备?