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

Core Data Earthquakes Demo预览时崩溃问题求助

Core Data Earthquakes Demo 预览崩溃问题

我正在学习Core Data,测试苹果官方的「Earthquakes - Loading and Display a large Data Feed」Demo时遇到了Canvas预览崩溃的问题:只要使用Quake.preview,编辑器就会崩溃。尝试查看崩溃日志但无法定位原因,将ContentView中的provider从.preview改为.shared后就不会崩溃。请问有人知道原因吗?

相关代码:

ContentView PreviewProvider代码

struct ContentView_Previews: PreviewProvider {
    static let quakesProvider = QuakesProvider.preview
    static var previews: some View {
        ContentView(quakesProvider: quakesProvider)
            
            .environment(\.managedObjectContext,
                          quakesProvider.container.viewContext)
    }
}

Quake 预览相关代码

/// An earthquake for use with canvas previews.
static var preview: Quake {
    let quakes = Quake.makePreviews(count: 1)
    return quakes[0]
}

static func makePreviews(count: Int) -> [Quake] {
    var quakes: [Quake] = []
    let viewContext = QuakesProvider.preview.container.viewContext
    for index in 0..<count {
        let quake = Quake(context: viewContext)
        quake.code = UUID().uuidString
        quake.time = Date().addingTimeInterval(Double(index) * -300)
        quake.magnitude = .random(in: -1.1...10.0)
        quake.place = "15km SSW of Cupertino, CA"
        quakes.append(quake)
    }
    return quakes
}

QuakesProvider 预览代码

/// A quakes provider for use with canvas previews.
static let preview: QuakesProvider = {
    let provider = QuakesProvider(inMemory: true)
    Quake.makePreviews(count: 10)
    return provider
}()

问题原因与解决方法

问题出在循环依赖和上下文初始化顺序冲突:

  • QuakesProvider.preview的初始化闭包里调用了Quake.makePreviews(count:10),而makePreviews又会直接访问QuakesProvider.preview.container.viewContext——此时QuakesProvider.preview还在初始化过程中,Core Data上下文尚未完全创建就被调用,直接触发了编辑器崩溃。
  • 换成.shared不会崩溃,是因为.shared的初始化逻辑没有这种循环依赖,上下文是完全初始化完成后才被使用的。

修复方案:

  1. 修改QuakesProvider.preview,把测试数据创建逻辑放在初始化内部,避免外部调用带来的循环依赖:
static let preview: QuakesProvider = {
    let provider = QuakesProvider(inMemory: true)
    let viewContext = provider.container.viewContext
    for index in 0..<10 {
        let quake = Quake(context: viewContext)
        quake.code = UUID().uuidString
        quake.time = Date().addingTimeInterval(Double(index) * -300)
        quake.magnitude = .random(in: -1.1...10.0)
        quake.place = "15km SSW of Cupertino, CA"
    }
    return provider
}()
  1. 调整Quake的预览方法,让它接收外部传入的上下文,不再直接依赖QuakesProvider.preview:
static func makePreviews(count: Int, context: NSManagedObjectContext) -> [Quake] {
    var quakes: [Quake] = []
    for index in 0..<count {
        let quake = Quake(context: context)
        quake.code = UUID().uuidString
        quake.time = Date().addingTimeInterval(Double(index) * -300)
        quake.magnitude = .random(in: -1.1...10.0)
        quake.place = "15km SSW of Cupertino, CA"
        quakes.append(quake)
    }
    return quakes
}

static var preview: Quake {
    let provider = QuakesProvider.preview
    let quakes = Quake.makePreviews(count: 1, context: provider.container.viewContext)
    return quakes[0]
}

这样就能打破循环依赖,确保Core Data上下文完全初始化后再被使用,Canvas预览就不会崩溃了。

内容的提问来源于stack exchange,提问作者Noem

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 02:00:32