最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

swift - CoreData in framework crash when using Preview - Stack Overflow

programmeradmin4浏览0评论

I have a project with 3 targets:

  • main application
  • an extension
  • framework (with coredata management for sharing with main app and extension)

I set App Groups for main app and extension. When I trying to preview in Xcode it crash (preview), maybe it's due to sandbox restriction to "/dev/null".

Persistence.swift:

public struct PersistenceController {
public static let shared = PersistenceController()

public static var preview: PersistenceController = {.  <---- Line 14
    let result = PersistenceController(inMemory: true)
    let viewContext = result.container.viewContext
    for _ in 0..<10 {
        let newItem = Item(context: viewContext)
        newItem.timestamp = Date()
    }
    do {
       try viewContext.save()
    } catch {
        // Replace this implementation with code to handle the error appropriately.
        // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        let nsError = error as NSError
        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
    }
    return result
}()

public let container: NSPersistentContainer

public init(inMemory: Bool = false) {
    let groupName = "group.xxx"
    let fileName = "database.sqlite"

    container = NSPersistentContainer(name: "xxxxxx")
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null"). <--- Line 68
    }
    else {
        let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupName)!
        let storeURL = containerURL.appendingPathComponent(fileName)
        let description = NSPersistentStoreDescription(url: storeURL)
        container.persistentStoreDescriptions = [description]
    }
    
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    container.viewContext.automaticallyMergesChangesFromParent = true
 }
}

ContentView.swift:

struct ContentView: View {


var body: some View {
    VStack {
        Image(systemName: "globe")
            .imageScale(.large)
            .foregroundStyle(.tint)
        Text("Hello, world!")
    }
    .padding()
    }
}

#Preview {
    ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}

Crash Report:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib                     0x102e0bf9e closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 318
1   libswiftCore.dylib                     0x102e0be1e closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 366
2   libswiftCore.dylib                     0x102e0bb5b closure #1 in _assertionFailure(_:_:file:line:flags:) + 123
3   libswiftCore.dylib                     0x102e0b816 _assertionFailure(_:_:file:line:flags:) + 230
4   CallerData                             0x101a46d36 PersistenceController.init(inMemory:) + 982 (Persistence.swift:68)
5   CallerData                             0x101a47423 closure #1 in variable initialization expression of static PersistenceController.preview + 51 (Persistence.swift:15)
6   CallerData                             0x101a473d9 one-time initialization function for preview + 9 (Persistence.swift:14)
7   libdispatch.dylib                      0x1040c6d3a _dispatch_client_callout + 8
8   libdispatch.dylib                      0x1040c80f3 _dispatch_once_callout + 20
9   CallerData                             0x101a474d1 PersistenceController.preview.unsafeMutableAddressor + 49 (Persistence.swift:14)
10  ContentView.1.preview-thunk.dylib          0x1019d0f48 closure #1 in static $s41ShieldUp_PreviewReplacement_ContentView_133_BD1FE069A66FD2100B578D7DDB7CD228Ll0C0fMf_15PreviewRegistryfMu_.makePreview() + 40 (@__swiftmacro_41ShieldUp_PreviewReplacement_ContentView_133_BD1FE069A66FD2100B578D7DDB7CD228Ll0C0fMf_.swift:9)
11  PreviewsInjection                      0x101d74386 0x101d36000 + 254854
12  PreviewsInjection                      0x101d7525d 0x101d36000 + 258653
13  libswift_Concurrency.dylib             0x103e026dc static MainActor.assumeIsolated<A>(_:file:line:) + 140
14  PreviewsInjection                      0x101d740e5 0x101d36000 + 254181
15  PreviewsInjection                      0x101d78108 0x101d36000 + 270600
16  PreviewsInjection                      0x101d78c1c 0x101d36000 + 273436
17  PreviewsInjection                      0x101d659fd 0x101d36000 + 195069
18  PreviewsInjection                      0x101d6886a 0x101d36000 + 206954
19  PreviewsInjection                      0x101d4f620 0x101d36000 + 103968
20  PreviewsInjection                      0x101d4fae4 0x101d36000 + 105188
21  PreviewsInjection                      0x101d6a3e0 0x101d36000 + 213984
22  PreviewsInjection                      0x101d3e3e3 0x101d36000 + 33763
23  PreviewsInjection                      0x101d3da75 0x101d36000 + 31349
24  PreviewsFoundation                     0x131969ed9 0x1318c9000 + 659161
25  libdispatch.dylib                      0x1040c5a90 _dispatch_call_block_and_release + 12
26  libdispatch.dylib                      0x1040c6d3a _dispatch_client_callout + 8
27  libdispatch.dylib                      0x1040d5ac0 _dispatch_main_queue_drain + 1420
28  libdispatch.dylib                      0x1040d5526 _dispatch_main_queue_callback_4CF + 31
29  CoreFoundation                         0x102344dc4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
30  CoreFoundation                         0x10233f6ff __CFRunLoopRun + 2463
31  CoreFoundation                         0x10233e97d CFRunLoopRunSpecific + 557
32  GraphicsServices                       0x104ec108f GSEventRunModal + 137
33  UIKitCore                              0x116efc53d -[UIApplication _run] + 972
34  UIKitCore                              0x116f00fab UIApplicationMain + 123
35  SwiftUI                                0x10acc2eda 0x109c7f000 + 17055450
36  SwiftUI                                0x10acc2d93 0x109c7f000 + 17055123
37  SwiftUI                                0x10a9630d7 0x109c7f000 + 13517015
38  ShieldUp                               0x1015f1d2e static ShieldUpApp.$main() + 30
39  ShieldUp                               0x1015f1df9 main + 9 (ShieldUpApp.swift:12)
40  dyld_sim                               0x1017783e0 start_sim + 10
41  dyld                                   0x109b85418 start + 1896

I have a project with 3 targets:

  • main application
  • an extension
  • framework (with coredata management for sharing with main app and extension)

I set App Groups for main app and extension. When I trying to preview in Xcode it crash (preview), maybe it's due to sandbox restriction to "/dev/null".

Persistence.swift:

public struct PersistenceController {
public static let shared = PersistenceController()

public static var preview: PersistenceController = {.  <---- Line 14
    let result = PersistenceController(inMemory: true)
    let viewContext = result.container.viewContext
    for _ in 0..<10 {
        let newItem = Item(context: viewContext)
        newItem.timestamp = Date()
    }
    do {
       try viewContext.save()
    } catch {
        // Replace this implementation with code to handle the error appropriately.
        // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
        let nsError = error as NSError
        fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
    }
    return result
}()

public let container: NSPersistentContainer

public init(inMemory: Bool = false) {
    let groupName = "group.xxx"
    let fileName = "database.sqlite"

    container = NSPersistentContainer(name: "xxxxxx")
    if inMemory {
        container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null"). <--- Line 68
    }
    else {
        let containerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: groupName)!
        let storeURL = containerURL.appendingPathComponent(fileName)
        let description = NSPersistentStoreDescription(url: storeURL)
        container.persistentStoreDescriptions = [description]
    }
    
    
    container.loadPersistentStores(completionHandler: { (storeDescription, error) in
        if let error = error as NSError? {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

            /*
             Typical reasons for an error here include:
             * The parent directory does not exist, cannot be created, or disallows writing.
             * The persistent store is not accessible, due to permissions or data protection when the device is locked.
             * The device is out of space.
             * The store could not be migrated to the current model version.
             Check the error message to determine what the actual problem was.
             */
            fatalError("Unresolved error \(error), \(error.userInfo)")
        }
    })
    container.viewContext.automaticallyMergesChangesFromParent = true
 }
}

ContentView.swift:

struct ContentView: View {


var body: some View {
    VStack {
        Image(systemName: "globe")
            .imageScale(.large)
            .foregroundStyle(.tint)
        Text("Hello, world!")
    }
    .padding()
    }
}

#Preview {
    ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}

Crash Report:

Thread 0 Crashed::  Dispatch queue: com.apple.main-thread
0   libswiftCore.dylib                     0x102e0bf9e closure #1 in closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 318
1   libswiftCore.dylib                     0x102e0be1e closure #1 in closure #1 in _assertionFailure(_:_:file:line:flags:) + 366
2   libswiftCore.dylib                     0x102e0bb5b closure #1 in _assertionFailure(_:_:file:line:flags:) + 123
3   libswiftCore.dylib                     0x102e0b816 _assertionFailure(_:_:file:line:flags:) + 230
4   CallerData                             0x101a46d36 PersistenceController.init(inMemory:) + 982 (Persistence.swift:68)
5   CallerData                             0x101a47423 closure #1 in variable initialization expression of static PersistenceController.preview + 51 (Persistence.swift:15)
6   CallerData                             0x101a473d9 one-time initialization function for preview + 9 (Persistence.swift:14)
7   libdispatch.dylib                      0x1040c6d3a _dispatch_client_callout + 8
8   libdispatch.dylib                      0x1040c80f3 _dispatch_once_callout + 20
9   CallerData                             0x101a474d1 PersistenceController.preview.unsafeMutableAddressor + 49 (Persistence.swift:14)
10  ContentView.1.preview-thunk.dylib          0x1019d0f48 closure #1 in static $s41ShieldUp_PreviewReplacement_ContentView_133_BD1FE069A66FD2100B578D7DDB7CD228Ll0C0fMf_15PreviewRegistryfMu_.makePreview() + 40 (@__swiftmacro_41ShieldUp_PreviewReplacement_ContentView_133_BD1FE069A66FD2100B578D7DDB7CD228Ll0C0fMf_.swift:9)
11  PreviewsInjection                      0x101d74386 0x101d36000 + 254854
12  PreviewsInjection                      0x101d7525d 0x101d36000 + 258653
13  libswift_Concurrency.dylib             0x103e026dc static MainActor.assumeIsolated<A>(_:file:line:) + 140
14  PreviewsInjection                      0x101d740e5 0x101d36000 + 254181
15  PreviewsInjection                      0x101d78108 0x101d36000 + 270600
16  PreviewsInjection                      0x101d78c1c 0x101d36000 + 273436
17  PreviewsInjection                      0x101d659fd 0x101d36000 + 195069
18  PreviewsInjection                      0x101d6886a 0x101d36000 + 206954
19  PreviewsInjection                      0x101d4f620 0x101d36000 + 103968
20  PreviewsInjection                      0x101d4fae4 0x101d36000 + 105188
21  PreviewsInjection                      0x101d6a3e0 0x101d36000 + 213984
22  PreviewsInjection                      0x101d3e3e3 0x101d36000 + 33763
23  PreviewsInjection                      0x101d3da75 0x101d36000 + 31349
24  PreviewsFoundation                     0x131969ed9 0x1318c9000 + 659161
25  libdispatch.dylib                      0x1040c5a90 _dispatch_call_block_and_release + 12
26  libdispatch.dylib                      0x1040c6d3a _dispatch_client_callout + 8
27  libdispatch.dylib                      0x1040d5ac0 _dispatch_main_queue_drain + 1420
28  libdispatch.dylib                      0x1040d5526 _dispatch_main_queue_callback_4CF + 31
29  CoreFoundation                         0x102344dc4 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
30  CoreFoundation                         0x10233f6ff __CFRunLoopRun + 2463
31  CoreFoundation                         0x10233e97d CFRunLoopRunSpecific + 557
32  GraphicsServices                       0x104ec108f GSEventRunModal + 137
33  UIKitCore                              0x116efc53d -[UIApplication _run] + 972
34  UIKitCore                              0x116f00fab UIApplicationMain + 123
35  SwiftUI                                0x10acc2eda 0x109c7f000 + 17055450
36  SwiftUI                                0x10acc2d93 0x109c7f000 + 17055123
37  SwiftUI                                0x10a9630d7 0x109c7f000 + 13517015
38  ShieldUp                               0x1015f1d2e static ShieldUpApp.$main() + 30
39  ShieldUp                               0x1015f1df9 main + 9 (ShieldUpApp.swift:12)
40  dyld_sim                               0x1017783e0 start_sim + 10
41  dyld                                   0x109b85418 start + 1896
Share Improve this question edited Mar 16 at 6:04 koen 5,7537 gold badges58 silver badges102 bronze badges asked Mar 15 at 15:44 niskah-medianiskah-media 11 bronze badge 0
Add a comment  | 

1 Answer 1

Reset to default 0

It’s an ownership issue. You are not keeping a strong reference to your PersistenceController and it drops out of scope and is released leaving the context orphaned and crashy.

Try

#Preview {
    let controller = PersistenceController.preview
    ContentView().environment(\.managedObjectContext,controller.container.viewContext)
}

Which should be enough to keep the controller in scope during the preview.

You can put a print in a deinit override in PersistenceController to check if this is actually the case.

发布评论

评论列表(0)

  1. 暂无评论