错误场景下调用completionHandler致App崩溃锁死问题求助
分析你的Completion Handler崩溃/锁死问题
这种情况我之前也碰到过好几次,大概率是线程问题或者completion handler被重复调用/提前释放导致的,咱们一步步来排查:
1. 先确认线程是否合规
错误检查逻辑里很可能是在后台线程调用了completion handler,但弹窗这类UI操作必须在主线程执行。比如你可能写了类似这样的代码:
// 错误示例:后台线程直接触发UI相关的completion DispatchQueue.global().async { if self.checkForError() { completion(false) // 这里直接操作UI会触发崩溃 } }
解决办法:调用completion时强制切回主线程:
DispatchQueue.main.async { completion(false) }
2. 排查是否重复调用了Completion Handler
错误处理分支里可能没及时终止流程,导致后续代码又调用了一次completion。比如:
func fetchData(completion: @escaping (Bool) -> Void) { if let error = self.validateParams() { completion(false) // 这里调用了一次 } // 后面的业务逻辑又不小心调用了一次 completion(true) }
解决办法:调用completion后立刻return,阻断后续流程:
if let error = self.validateParams() { completion(false) return // 加上return避免重复调用 }
3. 检查是否存在循环引用或handler提前释放
如果你的completion handler里强引用了self,可能导致循环引用;或者错误发生时,持有completion的对象已经被释放,触发野指针崩溃。比如:
// 错误示例:强引用self引发循环 self.fetchData { [self] success in if success { self.showSuccessPopup() } }
解决办法:改用弱引用打破循环:
self.fetchData { [weak self] success in guard let self = self else { return } if success { self.showSuccessPopup() } }
4. 警惕主线程死锁
如果错误检查逻辑本身就在主线程,而completion handler里又做了同步等待主线程的操作,就会直接死锁。比如:
// 错误示例:主线程里用sync调用completion DispatchQueue.main.sync { completion(false) // 主线程同步等待自己,直接死锁 }
解决办法:把sync换成async,避免主线程阻塞等待。
你可以先从这几个方向排查,如果能贴出相关的代码片段,能更精准定位问题~
内容的提问来源于stack exchange,提问作者bwhite
相关产品推荐
相关产品推荐

