Home > Mobile >  How to making a global Publisher?
How to making a global Publisher?

Time:05-24

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
        
    }
}
  • Related