如何解决登出清除Core Data时的随机崩溃问题?
解决Core Data枚举删除时的“集合被修改”崩溃问题
问题根源
崩溃的核心原因有两点:
- 你枚举的
cachedResults是Core Data返回的活集合(与上下文绑定的动态集合),执行delete操作时会直接修改该集合的内部结构,触发“枚举过程中集合被修改”的异常。 - 代码存在多线程安全隐患:
viewContext默认绑定主线程,若clearConversationList在非主线程调用,直接执行delete属于线程违规;而save方法异步切换到主线程的逻辑,会进一步加剧上下文状态的混乱。
修复方案
1. 将fetch结果转为独立数组
把Core Data返回的集合转换成普通数组,断开与上下文的绑定,确保枚举时的集合不受删除操作影响:
let cachedResults = Array(try coreDataContext.fetch(fetchRequest))
2. 确保Core Data操作在正确线程执行
利用Core Data上下文的performAndWait方法,强制所有操作在上下文关联的线程(viewContext对应主线程)执行,替代手动加锁:
func clearConversationList() { coreDataContext.performAndWait { do { let fetchRequest: NSFetchRequest<PersistentConversationDataItem> = PersistentConversationDataItem.fetchRequest() let cachedResults = Array(try coreDataContext.fetch(fetchRequest)) cachedResults.forEach { coreDataContext.delete($0) } save() } catch { print("清除会话列表失败: \(error)") } } }
3. 优化save方法的线程逻辑
移除DispatchQueue.main.async,改用上下文的perform方法,确保保存操作也在正确线程执行:
func save() { coreDataContext.perform { if self.coreDataContext.hasChanges { do { try self.coreDataContext.save() } catch { if let error = error as NSError? { print("保存Core Data失败: \(error), \(error.userInfo)") } } } } }
额外说明
移除原代码中的objc_sync_enter/exit手动锁,因为Core Data上下文的perform/performAndWait已经提供了线程安全的执行机制,手动加锁容易引发死锁或其他线程问题。
内容的提问来源于stack exchange,提问作者Faheem
相关产品推荐
相关产品推荐

