在 Swift 中,这会在运行时崩溃:
class EmptyData: BindableObject {
let didChange = PassthroughSubject<EmptyData, Never>()
}
struct RandomView : View {
@EnvironmentObject var emptyData: EmptyData
@EnvironmentObject var emptyData2: EmptyData
var body: some View {
Text("Hello World!")
}
}
并在SceneDelegate.swift
:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let window = UIWindow(frame: UIScreen.main.bounds)
// The emptyData variables are not initialized as seen below
window.rootViewController = UIHostingController(rootView: RandomView())
self.window = window
window.makeKeyAndVisible()
}
线程 1:EXC_BAD_INSTRUCTION(代码=EXC_I386_INVOP,子代码=0x0)
解决问题并不难,但很奇怪:
window.rootViewController = UIHostingController(rootView: RandomView().environmentObject(EmptyData()))
那么这里发生了什么?我通过EmptyData()
了,SwiftUI 决定两者都emptyData
应该emptyData2
使用相同的对象引用进行初始化?我还可以将其他甚至不存在的环境对象作为RandomView
实例中的变量传递:
window.rootViewController = UIHostingController(rootView: RandomView().environmentObject(EmptyData()).environmentObject(SomeData()))
而且 SwiftUI 只是愉快地运行,虽然SomeData()
没有在实例中的任何地方使用,RandomView()
并且在我看来应该触发编译时错误。
为什么在编译时允许未初始化的值而不在初始化对象时初始化它们,为什么我们可以自由地传递环境实例而不对它们做任何事情?对我来说看起来有点像 Javascript,我喜欢 Swift 中强大的静态安全类型……我不明白为什么成员初始化器只生成一个将环境变量作为参数的初始化器。