Swift 3:收到APNS推送通知时如何唤起应用显示短信界面?
在Swift 3中通过APNS推送唤起应用并展示短信界面
我来帮你搞定这个需求!要在收到APNS推送时自动唤起应用并弹出MFMessageComposeViewController,核心要解决两个问题:让应用从后台切换到前台,以及正确获取当前顶层ViewController来展示短信界面。下面是具体的实现步骤和代码:
1. 确保推送Payload支持后台唤醒
首先,你的APNS推送Payload必须包含content-available: 1,这样应用在后台时才能触发didReceiveRemoteNotification方法。示例Payload如下:
{ "aps": { "alert": "点击查看短信请求", "badge": 1, "sound": "default", "content-available": 1 }, "recipients": ["13800138000"], // 可选:从推送传递收件人 "messageBody": "这是预设的短信内容" // 可选:从推送传递短信内容 }
2. 修改didReceiveRemoteNotification方法
注意要使用带fetchCompletionHandler的重载方法,这是后台唤醒的标准回调。然后在方法里完成三个关键操作:唤醒应用到前台、获取顶层VC、展示短信界面。
func application(_ application: UIApplication, didReceiveRemoteNotification data: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) { print("My Push: \(data)") // 步骤1:将应用从后台唤起到前台 if application.applicationState == .background { application.applicationIconBadgeNumber = 0 // 清除推送角标 // 用自定义URL Scheme唤起应用(需要先在Info.plist配置) guard let appURL = URL(string: "your-app-scheme://") else { completionHandler(.failed) return } application.perform(#selector(UIApplication.openURL(_:)), with: appURL) } // 步骤2:获取当前顶层ViewController func getTopViewController() -> UIViewController? { var topVC = UIApplication.shared.keyWindow?.rootViewController while let presentedVC = topVC?.presentedViewController { topVC = presentedVC // 处理导航控制器和标签控制器的嵌套情况 if let navVC = topVC as? UINavigationController { topVC = navVC.visibleViewController } else if let tabVC = topVC as? UITabBarController { topVC = tabVC.selectedViewController } } return topVC } guard let topViewController = getTopViewController() else { print("无法获取顶层ViewController") completionHandler(.failed) return } // 步骤3:检查设备是否支持短信功能 guard MFMessageComposeViewController.canSendText() else { print("当前设备不支持短信功能") completionHandler(.failed) return } // 步骤4:配置并展示短信界面 let messageVC = MFMessageComposeViewController() messageVC.messageComposeDelegate = self // 必须设置代理,否则无法关闭界面 // 从推送Payload中读取预设的收件人和内容(可选) if let recipients = data["recipients"] as? [String] { messageVC.recipients = recipients } if let body = data["messageBody"] as? String { messageVC.body = body } // 必须在主线程执行UI操作 DispatchQueue.main.async { topViewController.present(messageVC, animated: true, completion: nil) } completionHandler(.newData) }
3. 实现短信界面的代理方法
别忘了在AppDelegate里遵循MFMessageComposeViewControllerDelegate协议,并实现关闭界面的方法:
extension AppDelegate: MFMessageComposeViewControllerDelegate { func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) { // 根据result处理不同的完成状态(可选) switch result { case .cancelled: print("短信发送取消") case .sent: print("短信已发送") case .failed: print("短信发送失败") @unknown default: break } // 关闭短信界面 controller.dismiss(animated: true, completion: nil) } }
4. 配置自定义URL Scheme
在Info.plist里添加URL Types,设置一个自定义的Scheme(比如your-app-scheme),这样才能通过openURL唤起应用到前台。
注意事项
- 测试时请使用真实设备,模拟器不支持短信功能。
- 确保用户已经授予应用推送通知权限,并且开启了“后台App刷新”权限。
- 如果应用完全被杀死(不是后台运行),
didReceiveRemoteNotification不会触发,这种情况需要用户点击推送通知才能唤起应用,之后再展示短信界面。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

