搜索框输入字母触发Thread 1: EXC_BAD_INSTRUCTION崩溃如何排查
问题原因
你遇到的EXC_BAD_INSTRUCTION崩溃属于Swift运行时的强制断言失败,结合「只有触发匹配结果时才崩溃」的特征,核心问题出在以下几个常见场景:
- CollectionView数据源取值错误
你的dataSource是[String: DeviceType]类型的无序字典,大概率你在UICollectionViewDataSource的cellForItemAt方法中,直接通过索引下标取字典的keys/values数组元素:
// 错误写法示例,会在索引超出数组范围时触发崩溃 let keyword = Array(dataSource.keys)[indexPath.item]
当搜索无结果时dataSource为空,返回的cell数量为0不会走到取值逻辑;一旦有匹配结果,若dataSource的数量在reloadData和cell渲染的间隙发生变化,就会出现数组下标越界崩溃。
2. 工具类内部强制解包失败StringUtility.cleaning(_:)方法内部可能存在隐式强制解包逻辑,只有当传入非特殊字符的字母内容时,才会触发解空崩溃。
3. 关键词数组线程不安全
遍历mainDeviceKeywords/importDeviceKeywords/exportDeviceKeywords三个全局数组时,如果有其它子线程同时在修改这三个数组的内容,会触发遍历过程中的内存错误。
修复方案
- 首先调整数据源结构,将字典改为有序数组避免索引取值异常:
// 定义结构存储匹配结果 struct SearchResult { let keyword: String let type: DeviceType } // 修改filteredKeywords返回值为有序数组 static func filteredKeywords(byString string: String?) -> [SearchResult] { guard let string = string else { return [] } let cleanString = StringUtility.cleaning(string).lowercased() var results = [SearchResult]() // 遍历添加结果 mainDeviceKeywords.forEach { keyword in if keyword.lowercased().contains(cleanString) { results.append(SearchResult(keyword: keyword, type: .deviceMain)) } } importDeviceKeywords.forEach { keyword in if keyword.lowercased().contains(cleanString) { results.append(SearchResult(keyword: keyword, type: .deviceImport)) } } exportDeviceKeywords.forEach { keyword in if keyword.lowercased().contains(cleanString) { results.append(SearchResult(keyword: keyword, type: .deviceExport)) } } return results }
- 检查
StringUtility.cleaning(_:)的实现,替换所有隐式强制解包(!)为可选绑定,避免解空崩溃。 - 给关键词数组的读写操作加线程锁,保证遍历关键词的操作始终在同一线程执行,避免多线程同时读写的内存问题。
内容的提问来源于stack exchange,提问作者devSwift
相关产品推荐
相关产品推荐

