I'm working on a SwiftUI app that uses core data. I'd like to use Paul's .snapshot extension to turn a specific view into an image. However, the resulting image doesn't have any content, and I get a purple run-time warning "Context in environment is not connected to a persistent store coordinator: <NSManagedObjectContext: 0x600000a9e3c0>"
Paul's snapshot extension:
extension View {
func snapshot() -> UIImage {
let controller = UIHostingController(rootView: self)
let view = controller.view
let targetSize = controller.view.intrinsicContentSize
view?.bounds = CGRect(origin: .zero, size: targetSize)
view?.backgroundColor = .clear
let renderer = UIGraphicsImageRenderer(size: targetSize)
return renderer.image { _ in
view?.drawHierarchy(in: controller.view.bounds, afterScreenUpdates: true)
}
}
}
The runtime warning is on the controller.view.intrinsicContentSize line.
I've done the 100 Days of SwiftUI, but not Swift, so I've got no familiarity with UIKit. As I read what's happening, when I create a new UIHostingController it appears to keep the managed object context, but that context loses reference to the NSPersistentContainer.
The snapshot extension works fine for me if I use it with any other view that doesn't include core data, so I know Paul's code is fine. Can anyone help me understand how to fix this? I think I want to create a UIHostingController with it's own NSPersistentContainer, but maybe someone fluent in UIKit can understand what's going wrong.
I've tried this:
let context = PersistenceController.shared.container.viewContext
let rootView = self
.environment(\.managedObjectContext, context)
But then I get a runtime error because the rootView seems to have lost the rest of the environmentObjects. Does creating a UIHostingController wipe out the environment and environmentObjects?
I've also tried the newer ImageRenderer in iOS16, and I get the same runtime warning that "Context in environment is not connected to a persistent store coordinator"
extension View {
@MainActor
func snapshot() -> UIImage {
if #available(iOS 16.0, *) {
let renderer = ImageRenderer(content: self)
return renderer.uiImage!
} else {
return UIImage(systemName: "questionark")!
}
}
}