You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:16:22