Cannot preview in this file - [App Name].app may have crashed on Xcode 11 Beta 5
Looks like Xcode issue. Try to use blue button instead of "Try Again".
I had the same problem, and I found out what the reason was.
I simply forgot to add the .environmentObject()
modifier
to ContentView()
in the preview part.
struct Content_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(NetworkManager())
}
}
That was why Xcode built it, without showing a code-mistake, but crashed on preview in canvas. - Simple mistake, I know.
As @graycampbell suggested, you need to ensure that the EnvironmentObject is provided to your ContentView in the SceneDelegate. While a lot of the preview / canvas mechanics are in a black box, Xcode's UI would suggest that invoking a new preview or refreshing an existing one, builds (or updates relevant parts of) a variant of your app even for the regular preview, as opposed to the "Live Preview". This process can fail if the SceneDelegate isn't set up correctly.
For your @Binding problem, Binding.constant(_:) should help. Per the SwiftUI Documentation .constant does the following:
Creates a binding with an immutable value.
This is what you want for your preview, instead of the @State your sample code shows. You can see an example of .constant in use in Section 3 of this Apple tutorial.
So instead of this:
#if DEBUG
struct ContentView_Previews: PreviewProvider {
@State static var test1 = "Some Preview String"
static var previews: some View {
ContentView(test123: $test1)
.environmentObject(NetworkManager())
}
}
#endif
you can do the following:
#if DEBUG
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(test123: .constant("Some Preview String"))
.environmentObject(NetworkManager())
}
}
#endif
With this change, previews of your code work perfectly for me. Keep in mind that you again need to provide a value to this Binding in your SceneDelegate or any other place in which you use this particular ContentView. Otherwise you will run into a problem similar to the one you faced with EnvironmentObject, just that this particular omission luckily is highlighted by a compiler error.
I'm assuming based on the code you provided that your SceneDelegate
looks like this:
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
I'm not going to pretend I know exactly what the canvas is doing behind the scenes when it generates a preview, but based on the fact that the error specifically states that the app may have crashed, I'm assuming that it's attempting to launch the entire app when it tries to generate a preview. Maybe it needs to use the SceneDelegate
to launch the preview, maybe it's something else entirely - I can't say for sure.
Regardless, the reason the app is crashing is because you aren't passing an environment object in your SceneDelegate
. Your SceneDelegate
should look like this:
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(NetworkManager()))
self.window = window
window.makeKeyAndVisible()
}