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
1 Answer
Reset to default 0It’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.