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

从后台线程更新UIProgressView进度时崩溃问题排查

解决后台更新Progress导致的崩溃问题

你遇到的问题本质是Progress类的属性线程不安全导致的崩溃——Progress的completedUnitCount、totalUnitCount这类属性并不是线程安全的,你在Core Data后台任务的线程里直接修改它,而UIProgressView在主线程通过KVO监听进度变化,线程之间的操作冲突就触发了崩溃。

核心原因

Progress对象的KVO通知是和它被创建的线程绑定的(你的downloadProgress是在主线程的init方法里初始化的),如果在其他线程直接修改它的属性,会打破这种线程一致性,引发不可预测的崩溃。

修复方案

所有对Progress属性的修改操作,都要切换到主线程执行,哪怕是在后台任务里。你可以用DispatchQueue.main.async把更新代码包裹起来,修改后的示例代码如下:

var downloadProgress: Progress

init() {
    downloadProgress = Progress()
}

func saveStuff() {
    let stuff: [[String: Any]] = // 你的字典数组
    // 主线程设置总任务数,避免线程冲突
    DispatchQueue.main.async {
        self.downloadProgress.totalUnitCount = Int64(stuff.count)
    }
    
    persistentContainer.performBackgroundTask { context in
        var completedTasks = 0
        for item in stuff {
            // 执行Core Data实体创建与属性填充
            let newEntity = YourCoreDataEntity(context: context)
            // 填充实体属性...
            
            do {
                try context.save()
                // 每次保存完成后,回到主线程更新进度
                DispatchQueue.main.async {
                    completedTasks += 1
                    self.downloadProgress.completedUnitCount = Int64(completedTasks)
                }
            } catch {
                print("Core Data保存失败: \(error.localizedDescription)")
            }
        }
    }
}

额外提示

如果你的后台任务逻辑更复杂,也可以考虑在后台线程创建一个独立的Progress对象追踪任务进度,等整个后台任务完成后,再把最终进度同步到主线程的downloadProgress上,但上面的方法是最直接解决当前崩溃的方案。

内容的提问来源于stack exchange,提问作者Mr.P

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 06:57:00