UITextView引发手势识别器依赖数量异常的原因及解决方案
问题原因
这个警告的核心原因是UITextView内部的手势识别器依赖关系未被正确清理:
- UITextView默认自带多组手势(比如长按选择、滚动相关手势),即便你设置了
isScrollEnabled = false和isEditable = false,其内部的手势逻辑仍会维持部分依赖链。 - 当你反复导航进入/退出该视图时,如果视图控制器或UITextView因强引用循环、外部强引用持有等问题无法被ARC正常销毁,每次新创建的UITextView都会新增一批手势依赖,旧的依赖又因对象未销毁留存内存,最终导致依赖数量不断累积,触发系统的阈值警告。
- UILabel没有复杂的内部手势系统,因此替换后不会出现这类问题。
解决方案(保留UITextView)
可以从内存管理、手势控制两个方向入手解决:
1. 排查并修复强引用循环,确保视图能被正常销毁
- 检查视图控制器代码,确认闭包捕获
self时是否使用了weak/unowned(比如配置UITextView的闭包、网络请求回调等场景)。 - 排查是否存在全局变量、父视图控制器等外部对象强引用该UITextView或其所在的视图控制器,导致它们无法被销毁。
- 可以在视图控制器的
deinit方法中添加日志,验证每次退出导航时控制器是否被销毁:
如果日志未打印,说明存在强引用问题,必须优先解决。deinit { print("当前视图控制器已销毁") }
2. 禁用不必要的交互特性,减少内部手势数量
既然不需要编辑和滚动功能,可以进一步禁用文本选择,减少UITextView内部的手势数量:
var notesTextView: UITextView = { let textView = UITextView() textView.textColor = Colors.blackText textView.font = Fonts.body textView.isScrollEnabled = false textView.isEditable = false textView.isSelectable = false // 新增:禁用选择手势,减少内部依赖 textView.allowsEditingTextAttributes = false // 可选:进一步关闭编辑相关属性 return textView }()
禁用选择后,UITextView会关闭文本选择相关的手势,从根源减少可能累积的依赖关系。
3. 在视图销毁前手动清理手势依赖(备选方案)
如果上述方法无效,可以在视图控制器的viewWillDisappear或deinit中手动清理UITextView的手势识别器:
override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) notesTextView.gestureRecognizers?.forEach { notesTextView.removeGestureRecognizer($0) } }
注意:这种方法可能影响UITextView的默认行为,建议仅在其他方案无效时使用。
4. 复用UITextView实例(可选)
如果该视图控制器被频繁创建销毁,可以考虑将UITextView提升到父容器(如导航控制器、全局缓存)中复用,避免每次创建新实例带来的手势依赖堆积。此方案需结合业务场景调整,并非通用解法。
内容的提问来源于stack exchange,提问作者Moses Harding
相关产品推荐
相关产品推荐

