我尝试做一个全球性的出版商,比如:
@Published var counter = 0
但是这里有一个错误:
Property wrappers are not yet supported in top-level code
如何在模型之间共享全局Publisher变量?
如果你想要一个全局变量以类似于@Published
属性的方式发布一个值,你可以这样做
var counter = CurrentValueSubject<Int,Never>(0)
let subscription = counter.sink { print("The counter is ($0)") }
counter1.value = 3
但是如果你正在使用SwiftUI,那么正如Joakim Danielson在评论中指出的那样,你应该考虑使值成为环境的一部分,而不是全局的。
这个解决方案看起来像:
private struct EnvironmentCounter: EnvironmentKey {
typealias Value = Int
static var defaultValue: Int = 0
static let farReachingCounter: String = "Far Reaching Counter"
}
extension EnvironmentValues {
var farReachingCounter: Int {
get { self[EnvironmentCounter.self] }
set { self[EnvironmentCounter.self] = newValue }
}
}
struct LeafView : View {
@Environment(.farReachingCounter) var counter : Int
var body: some View {
Text("The counter is (counter)")
}
}
struct IntermediateView : View {
var body: some View {
LeafView()
}
}
struct TopLevelView: View {
@State var counter = 0
var body: some View {
VStack {
IntermediateView()
HStack {
Button(action: { counter = counter + 1 }) {
Text("Increment")
}
Button(action: { counter = counter - 1 }) {
Text("Decrement")
}
}
}.environment(.farReachingCounter, counter)
}
}
PlaygroundSupport.PlaygroundPage.current.liveView = UIHostingController(rootView: TopLevelView())
这段代码声明了一个EnvironmentKey
,视图可以使用它从环境中提取值。在本例中,键为farReachingCounter
。
然后在EnvironmentValues
上声明一个扩展,该扩展在环境中获取和设置值,并从环境中获取值。
最后我展示了一个SwiftUI层次结构,其中TopLevelView
定义了整个层次结构的计数器值。有一个IntermediateView
根本不引用法院计数器(它只是在那里显示计数器通过环境向下传递视图层次结构)。然后LeafView
显示了如何从环境中提取自定义值。
farReachingCounter
对整个模块来说不是全局的,但它是TopLevelView
以下的SwiftUI环境的一部分。
解决方案如下:
class Counter: ObservableObject {
@Published var counter = 0
static var shared = Counter.init()
private init() { //Just to hide the method
}
}