You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何解决登出清除Core Data时的随机崩溃问题?

解决Core Data枚举删除时的“集合被修改”崩溃问题

问题根源

崩溃的核心原因有两点:

  1. 你枚举的cachedResults是Core Data返回的活集合(与上下文绑定的动态集合),执行delete操作时会直接修改该集合的内部结构,触发“枚举过程中集合被修改”的异常。
  2. 代码存在多线程安全隐患: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.05 08:57:03