在闭包中通过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
相关产品推荐
相关产品推荐

