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

MessageComposeViewController未调用代理问题求助

看来你卡在MessageComposeViewController的代理回调问题上了,我之前做短信功能时也踩过类似的坑,咱们一步步排查解决:

核心问题分析

你说发送/取消后控制器不消失,且代理方法没打印,大概率是代理没正确绑定或者处理短信的类实例生命周期太短被提前释放了。

具体排查&解决步骤

1. 确保SendMessage类正确遵循代理协议

不管你用Swift还是Objective-C,首先要确认类声明里已经加上了MFMessageComposeViewControllerDelegate协议,并且代理方法的签名完全正确(哪怕少个下划线都会失效):

Swift示例:

import MessageUI

// 必须继承NSObject,因为这是OC协议,需要NSObject的动态特性
class SendMessage: NSObject, MFMessageComposeViewControllerDelegate {
    // 显示短信控制器的方法
    func showMessageComposer(from parentVC: UIViewController) {
        guard MFMessageComposeViewController.canSendText() else {
            // 处理设备不支持短信的情况,比如iPad
            parentVC.showToast(message: "当前设备无法发送短信")
            return
        }
        
        let messageVC = MFMessageComposeViewController()
        messageVC.recipients = ["13xxxxxxxxx"] // 设置收件人
        messageVC.body = "我的问答游戏得分:90分!" // 设置短信内容
        // 关键:绑定代理到当前SendMessage实例
        messageVC.messageComposeDelegate = self
        
        parentVC.present(messageVC, animated: true)
    }
    
    // 必须严格匹配的代理方法,写错一个字符都不会触发!
    func messageComposeViewController(_ controller: MFMessageComposeViewController, didFinishWith result: MessageComposeResult) {
        print("代理方法触发!结果:\(result.rawValue)")
        // 手动关闭控制器,这一步不能忘
        controller.dismiss(animated: true)
        
        // 还可以根据result做后续处理,比如提示用户发送成功/失败
        switch result {
        case .sent:
            print("短信发送成功")
        case .cancelled:
            print("用户取消发送")
        case .failed:
            print("短信发送失败")
        @unknown default:
            break
        }
    }
    
    deinit {
        print("SendMessage实例被释放了") // 可以加这个打印,看是不是实例提前没了
    }
}

2. 保证SendMessage实例的生命周期足够长

很多人会犯的错误:在某个方法里创建SendMessage的临时局部变量,方法执行完后实例就被ARC释放了,代理自然没人响应。

错误示例:

// 错误:sendResult方法执行完,messageSender就被释放了
func sendResult() {
    let messageSender = SendMessage()
    messageSender.showMessageComposer(from: self)
}

正确做法:把SendMessage实例作为视图控制器的属性持有:

class GameViewController: UIViewController {
    // 作为属性持有,只要当前VC存在,这个实例就不会被释放
    private let messageSender = SendMessage()
    
    func sendGameResult() {
        messageSender.showMessageComposer(from: self)
    }
}

3. 其他可能的小坑

  • 检查是否用了正确的控制器present短信VC:必须用当前可见的视图控制器present,不要随便用UIApplication.shared.keyWindow?.rootViewController,可能导致上下文异常。
  • 测试时用真实设备:模拟器无法发送短信,虽然能打开短信界面,但代理回调可能有异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:51:07