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

在闭包中通过Delegate实现视图控制器间的数据传递问题

解决MKLocalSearch闭包中Delegate不执行的问题

嘿,我之前也踩过类似的坑——异步闭包里用Delegate传数据,总是没反应,大概率是这几个地方没处理好,咱们一个个捋:

1. 先把Delegate的引用关系搞对

Delegate必须用弱引用,不然很容易出现循环引用或者VC提前被释放的情况。首先你的协议得这么定义:

protocol SearchDataDelegate: AnyObject {
    func didReceiveSearchResult(_ result: MKLocalSearch.Response)
}

然后在发起搜索的VC里,delegate属性要加weak:

weak var delegate: SearchDataDelegate?

要是没加weak,等MKLocalSearch的异步闭包执行完,接收数据的VC可能已经被销毁了,Delegate方法自然不会触发。

2. 跳转时别忘了给Delegate赋值

因为你是纯代码写的跳转,比如push或者present第二个VC的时候,一定要手动设置delegate:

// 举个push的例子
let resultVC = ResultVC()
resultVC.delegate = self // 这里要确保当前VC遵循了SearchDataDelegate协议
navigationController?.pushViewController(resultVC, animated: true)

我见过很多人栽在这——跳转的时候光顾着创建VC,忘了给delegate赋值,闭包里调用的时候delegate是nil,当然没反应。

3. 异步闭包里要先确认Delegate还活着

MKLocalSearch的闭包是异步执行的,有可能在搜索完成前,接收数据的VC已经被pop或者dismiss了。所以在闭包里调用Delegate方法前,最好先做个判断:

let searchRequest = MKLocalSearch.Request()
searchRequest.naturalLanguageQuery = "你要搜的内容"
let search = MKLocalSearch(request: searchRequest)

// 这里用[weak self]捕获,避免循环引用
search.start { [weak self] response, error in
    guard let self = self, let response = response, error == nil else { return }
    // 先检查delegate是否存在,再调用方法
    self.delegate?.didReceiveSearchResult(response)
}

4. 确认接收VC正确遵循了协议

比如你的ResultVC得这么写,确保协议方法的签名完全一致:

class ResultVC: UIViewController, SearchDataDelegate {
    override func viewDidLoad() {
        super.viewDidLoad()
        // 你的初始化代码
    }
    
    // 方法名、参数类型必须和协议里的完全一样
    func didReceiveSearchResult(_ result: MKLocalSearch.Response) {
        // 在这里处理搜索结果,比如刷新列表或者更新UI
        print("收到\(result.mapItems.count)条搜索结果")
    }
}

要是方法名写错了,或者参数类型不对,编译器可能不会报错,但方法就是不会被调用。

备选方案:用闭包代替Delegate

要是Delegate还是搞不定,试试用闭包传数据,有时候在异步场景下更省心:
在ResultVC里定义一个闭包属性:

var onSearchResult: ((MKLocalSearch.Response) -> Void)?

然后在跳转的时候给闭包赋值:

let resultVC = ResultVC()
resultVC.onSearchResult = { response in
    // 直接在这里处理结果,或者让ResultVC自己处理
    print("闭包收到结果:\(response.mapItems.count)")
}
navigationController?.pushViewController(resultVC, animated: true)

最后在MKLocalSearch的闭包里调用:

search.start { response, error in
    guard let response = response, error == nil else { return }
    self.onSearchResult?(response)
}

你可以对照自己的简化代码,逐一排查这几个点,应该就能解决问题啦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:23:44