I try to maing a global publisher,like:
@Published var counter = 0
But here is a error:
Property wrappers are not yet supported in top-level code
How to share global Publisher variables between models?
CodePudding user response:
If you want a global variable that publishes a value in a similar way to an @Published
property you can do
var counter = CurrentValueSubject<Int,Never>(0)
let subscription = counter.sink { print("The counter is \($0)") }
counter1.value = 3
But if you are using SwiftUI then as Joakim Danielson pointed out in comments you should look into making the value part of the Environment rather than having a global.
That solution would look something like:
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())
This code declares an EnvironmentKey
that views can use to pull values out of the Environment. In this case the key is farReachingCounter
.
Then it declares an extension on EnvironmentValues
that gets and sets the value in and gets the value from the environment.
Finally I show a SwiftUI hierarchy where the TopLevelView
defines the counter value for its whole hierarchy. There is an IntermediateView
that doesn't reference the court counter at all (it's just there to show that the counter passes down the view hierarchy through the environment). Then the LeafView
shows how you can pull a custom value out of the environment.
The farReachingCounter
is not global to the whole module, but it is part of the SwiftUI environment from the TopLevelView
down.
CodePudding user response:
Here is the solution :
class Counter: ObservableObject {
@Published var counter = 0
static var shared = Counter.init()
private init() { //Just to hide the method
}
}