无法在此文件中预览-[App Name] .app可能在Xcode 11 Beta 5上崩溃了

时间:2019-08-03 17:21:44

标签: ios iphone xcode swiftui xcode11

如果我添加一个EnviromentObject属性包装器,则Xcode预览不起作用。每当我添加一个画布时,画布都不会建立,并且出现此错误:

  

无法在此文件中预览-[应用名称] .app可能崩溃了

如果我将EnviromentObject属性包装器替换为ObservedObject并对其进行初始化,则一切正常。

这是我的代码:

class NetworkManager: ObservableObject {

}

struct ContentView : View {
    @EnvironmentObject var networkManager: NetworkManager

    var body: some View {
        Text("Canvas not working")
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(NetworkManager())
    }
}
#endif

更新:

当我使用绑定时,它也不会加载预览:

struct ContentView : View {
    @EnvironmentObject var networkManager: NetworkManager
    @Binding var test123: String

    var body: some View {
        Text("Canvas not working")
    }
}

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    @State static var test1 = ""
    static var previews: some View {
        ContentView(test123: $test1).environmentObject(NetworkManager())
    }
}
#endif

5 个答案:

答案 0 :(得分:5)

按照@graycampbell的建议,您需要确保将EnvironmentObject提供给SceneDelegate中的ContentView。尽管许多预览/画布机制都在黑框中,但Xcode的UI建议使用新的预览或刷新现有的预览,甚至为常规预览构建(或更新)应用变体的形式,例如反对“实时预览”。如果SceneDelegate的设置不正确,此过程可能会失败。

对于您的@Binding问题,Binding.constant(_ :)应该会有所帮助。根据{{​​3}} .constant执行以下操作:

  

创建一个具有不变值的绑定。

这是您要预览的内容,而不是示例代码显示的@State。您可以在SwiftUI Documentation的第3节中看到一个使用.constant的示例。

所以代替这个:

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    @State static var test1 = "Some Preview String"
    static var previews: some View {
        ContentView(test123: $test1)
             .environmentObject(NetworkManager())
    }
}
#endif

您可以执行以下操作:

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView(test123: .constant("Some Preview String"))
            .environmentObject(NetworkManager())
    }
}
#endif

有了此更改,您的代码预览对我来说非常完美。 请记住,您再次需要在SceneDelegate或使用此特定ContentView的任何其他位置为此Binding提供一个值。否则,您将遇到与EnvironmentObject面临的问题类似的问题,只是幸运的是,编译器错误突出了这一特殊的遗漏。

答案 1 :(得分:2)

我遇到了同样的问题,并且找出了原因。 我只是忘了添加.environmentObject()修饰符 到预览部分中的ContentView()

struct Content_Previews: PreviewProvider {
    static var previews: some View {
       ContentView().environmentObject(NetworkManager())
    }
}

这就是为什么Xcode在不显示代码错误的情况下构建它的原因, 但在画布上预览时崩溃。 -简单的错误,我知道。

答案 2 :(得分:1)

我根据您提供的代码假设SceneDelegate如下所示:

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView())
    self.window = window
    window.makeKeyAndVisible()
}

我不会假装我确切地知道画布在生成预览时在幕后正在做什么,但是基于该错误专门指出该应用程序可能崩溃的事实,我假设它是在尝试生成预览时尝试启动整个应用程序。也许它需要使用SceneDelegate来启动预览,也许完全是另外一回事-我不能肯定地说。

无论如何,应用程序崩溃的原因是您没有在SceneDelegate中传递环境对象。您的SceneDelegate应该如下所示:

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(NetworkManager()))
    self.window = window
    window.makeKeyAndVisible()
}

答案 3 :(得分:0)

看起来像Xcode问题。尝试使用蓝色按钮代替“再试一次”。 enter image description here

答案 4 :(得分:0)

我确实有一个解决方法,但是是的,该错误确实在XCode中。
要解决此问题。您必须先设置SceneDelegate

if let windowScene = scene as? UIWindowScene {
    let window = UIWindow(windowScene: windowScene)
    window.rootViewController = UIHostingController(rootView: ContentView().environmentObject(NetworkManager()))
    self.window = window
    window.makeKeyAndVisible()
}. 

您还必须设置预览。看来您已经做到了。

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(NetworkManager())
    }
}. 

最后,只需在@State内声明一个ContentView@Published类型相同的@EnvironmentObject变量,无论是否将其用于绑定到ContentView没关系。

@State var bindingVar: Double = 0.0

正如我之前所说的,这是XCode错误,我不知道为什么ContentView需要一个相同类型的@State变量来开始预览@EnvironmentObject绑定的代码。
可能ContentView_Previews无法从@EnvironmentObject中找到绑定。

您可以在我的代码下面看到它,它像一个超级按钮。

enter image description here