如何修复iOS 15中'windows'被弃用问题(UIKit邮件控制器场景)
修复后的完整代码
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
相关产品推荐
相关产品推荐

