使用UITapGestureRecognizer触发BAD ACCESS崩溃,未进入回调求排查
问题分析与解决方案
核心问题:异步方法无法作为手势识别器的Action
UIKit的Target-Action机制不支持直接将async @objc方法作为手势识别器的action。异步方法的底层签名和传统同步@objc方法存在差异,运行时无法正确解析并调用该selector,直接触发BAD ACCESS内存错误,且永远不会进入目标方法。
修复步骤
将异步逻辑包裹在同步的@objc方法内部,通过Task启动异步任务:
// 手势添加代码保持不变 let gesture = UITapGestureRecognizer(target: self, action: #selector(self.goToKeyIdea)) gesture.numberOfTapsRequired = 1 kView.tag = num kView.isUserInteractionEnabled = true kView.addGestureRecognizer(gesture) // 修改后的响应方法 @objc func goToKeyIdea (_ sender: UITapGestureRecognizer) { Task { let canAccess = await MUser.sharedInstance.canAccessTextSummaries(book: self.data) if !canAccess { self.pay() } else { let params = [ "bookId": self.book.subid, "UserId": String(MUser.sharedInstance.userId) ] Flurry.log(eventName: "BookSummaryRead", parameters: params) await MUser.sharedInstance.incrementRead() await MUser.sharedInstance.handleBookStarted(book: self.book) self.selectedKeyIdea = sender.view?.tag ?? 0 self.performSegue(withIdentifier: "toText", sender: nil) } } }
额外说明
- 你注释的
gesture.view?.tag = num确实无效,因为手势还未添加到kView上,此时gesture.view为nil,无需保留。 - 关于iOS版本:这不是iOS新版本的突发变更,而是Swift引入
async/await(iOS 15+)后,异步方法的签名不符合UIKit Target-Action的要求导致的,属于语言特性与UIKit交互的固有约束。 - 额外检查:确保持有手势的对象(比如当前视图控制器)没有被提前释放,避免因对象销毁导致的内存访问问题,但本次崩溃的核心原因是异步方法的selector绑定错误。
内容的提问来源于stack exchange,提问作者Rue Vitale
相关产品推荐
相关产品推荐

