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

如何修复iOS 15中'windows'被弃用问题(UIKit邮件控制器场景)

修复iOS 15+下UIApplication.shared.windows弃用问题,正确模态展示MFMailComposeViewController

修复后的完整代码

private func presentMailCompose() {
    guard MFMailComposeViewController.canSendMail() else {
        return
    }
    
    // 替换弃用的windows API,适配iOS15+
    let rootViewController: UIViewController? = {
        // 获取当前激活的UIWindowScene
        guard let scene = UIApplication.shared.connectedScenes
                .filter({ $0.activationState == .foregroundActive })
                .first as? UIWindowScene else {
            return nil
        }
        // 获取场景的keyWindow,再取rootViewController
        return scene.windows.filter({ $0.isKeyWindow }).first?.rootViewController
    }()
    
    let composeVC = MFMailComposeViewController()
    composeVC.mailComposeDelegate = mailComposeDelegate
    
    // 自定义邮件内容示例(可选)
    composeVC.setToRecipients(["example@domain.com"])
    composeVC.setSubject("邮件主题")
    composeVC.setMessageBody("邮件内容", isHTML: false)
    
    rootViewController?.present(composeVC, animated: true)
}

关键修复点说明

  • 替换弃用API:用UIApplication.shared.connectedScenes替代UIApplication.shared.windows,这是iOS15官方推荐的多场景适配方案
  • 筛选激活场景:通过activationState == .foregroundActive确保拿到当前用户正在交互的场景,避免多窗口场景下的错误
  • 安全获取根控制器:通过可选绑定和过滤,避免因为场景或窗口不存在导致的崩溃

更优写法(如果在ViewController内部调用)

如果这个方法是在某个UIViewController子类中实现的,无需全局查找根控制器,直接用当前控制器present更简洁:

private func presentMailCompose() {
    guard MFMailComposeViewController.canSendMail() else {
        return
    }
    
    let composeVC = MFMailComposeViewController()
    composeVC.mailComposeDelegate = mailComposeDelegate
    
    // 自定义邮件内容
    composeVC.setToRecipients(["example@domain.com"])
    
    present(composeVC, animated: true)
}

补充:邮件代理实现(避免内存泄漏)

别忘了实现MFMailComposeViewControllerDelegate,确保邮件界面关闭后正确释放资源:

extension YourClass: MFMailComposeViewControllerDelegate {
    func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
        controller.dismiss(animated: true)
    }
}

内容的提问来源于stack exchange,提问作者jchan12345

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 00:30:10