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.com.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
0

1 Answer 1

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.