无法在此文件中预览 - [App Name].app 可能已在 Xcode 11 Beta 5 上崩溃
Cannot preview in this file - [App Name].app may have crashed on Xcode 11 Beta 5
如果我添加 EnviromentObject
属性 包装器,Xcode 预览将不起作用。每次我添加一个 Canvas 都不会构建,我会收到此错误:
Cannot preview in this file - [App Name].app may have crashed
如果我用 ObservedObject
替换 EnviromentObject
属性 包装器并初始化它,一切正常。
这是我的代码:
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
看起来像 Xcode 问题。尝试使用蓝色按钮而不是 "Try Again"。
根据您提供的代码,我假设您的 SceneDelegate
看起来像这样:
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
我不会假装我确切地知道 canvas 在生成预览时在幕后做了什么,但基于错误明确指出应用程序可能已崩溃的事实,我假设它在尝试生成预览时试图启动整个应用程序。也许它需要使用 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()
}
正如@graycampbell 所建议的,您需要确保将 EnvironmentObject 提供给 SceneDelegate 中的 ContentView。虽然很多预览/canvas 机制都在黑盒中,但 Xcode 的 UI 会建议调用新预览或刷新现有预览、构建(或更新相关部分) of) 应用程序的变体,即使是常规预览,也与 "Live Preview" 相对。如果 SceneDelegate 设置不正确,此过程可能会失败。
对于您的@Binding 问题,Binding.constant(_:) 应该有所帮助。根据 SwiftUI Documentation .constant 执行以下操作:
Creates a binding with an immutable value.
这是你想要的预览,而不是你的示例代码显示的@State。您可以在 this Apple tutorial.
的第 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 的任何其他地方为此绑定提供一个值。否则,您将 运行 陷入类似于您遇到 EnvironmentObject 的问题,只是幸运的是这一特定遗漏被编译器错误突出显示。
我确实有一个 解决方法,但是是的,错误确实存在于 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())
}
}.
最后,只需在您的 ContentView
中声明一个 @State
变量,与您 @Published
和 @EnvironmentObject
的类型相同,无论您是否将其用于绑定ContentView
中的任何地方都没有关系。
@State var bindingVar: Double = 0.0
正如我之前所说,这是 XCode 错误,我不知道为什么 ContentView
需要一个相同类型的 @State 变量来开始预览 @EnvironmentObject
绑定代码。
可能是 ContentView_Previews
无法从 @EnvironmentObject
中找到绑定。
您可以在我的代码中看到下面的内容,它非常有效。
我遇到了同样的问题,我找到了原因。
我只是忘了添加 .environmentObject()
修饰符
到 ContentView()
在预览部分。
struct Content_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(NetworkManager())
}
}
这就是 Xcode 构建它的原因,没有显示代码错误,
但在 canvas 中预览时崩溃了。 - 简单的错误,我知道。
如果我添加 EnviromentObject
属性 包装器,Xcode 预览将不起作用。每次我添加一个 Canvas 都不会构建,我会收到此错误:
Cannot preview in this file - [App Name].app may have crashed
如果我用 ObservedObject
替换 EnviromentObject
属性 包装器并初始化它,一切正常。
这是我的代码:
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
看起来像 Xcode 问题。尝试使用蓝色按钮而不是 "Try Again"。
根据您提供的代码,我假设您的 SceneDelegate
看起来像这样:
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: ContentView())
self.window = window
window.makeKeyAndVisible()
}
我不会假装我确切地知道 canvas 在生成预览时在幕后做了什么,但基于错误明确指出应用程序可能已崩溃的事实,我假设它在尝试生成预览时试图启动整个应用程序。也许它需要使用 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()
}
正如@graycampbell 所建议的,您需要确保将 EnvironmentObject 提供给 SceneDelegate 中的 ContentView。虽然很多预览/canvas 机制都在黑盒中,但 Xcode 的 UI 会建议调用新预览或刷新现有预览、构建(或更新相关部分) of) 应用程序的变体,即使是常规预览,也与 "Live Preview" 相对。如果 SceneDelegate 设置不正确,此过程可能会失败。
对于您的@Binding 问题,Binding.constant(_:) 应该有所帮助。根据 SwiftUI Documentation .constant 执行以下操作:
Creates a binding with an immutable value.
这是你想要的预览,而不是你的示例代码显示的@State。您可以在 this Apple tutorial.
的第 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 的任何其他地方为此绑定提供一个值。否则,您将 运行 陷入类似于您遇到 EnvironmentObject 的问题,只是幸运的是这一特定遗漏被编译器错误突出显示。
我确实有一个 解决方法,但是是的,错误确实存在于 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())
}
}.
最后,只需在您的 ContentView
中声明一个 @State
变量,与您 @Published
和 @EnvironmentObject
的类型相同,无论您是否将其用于绑定ContentView
中的任何地方都没有关系。
@State var bindingVar: Double = 0.0
正如我之前所说,这是 XCode 错误,我不知道为什么 ContentView
需要一个相同类型的 @State 变量来开始预览 @EnvironmentObject
绑定代码。
可能是 ContentView_Previews
无法从 @EnvironmentObject
中找到绑定。
您可以在我的代码中看到下面的内容,它非常有效。
我遇到了同样的问题,我找到了原因。
我只是忘了添加 .environmentObject()
修饰符
到 ContentView()
在预览部分。
struct Content_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(NetworkManager())
}
}
这就是 Xcode 构建它的原因,没有显示代码错误, 但在 canvas 中预览时崩溃了。 - 简单的错误,我知道。