Chris
Chris

Reputation: 8091

Why can't swiftui distinguish 2 different environment objects?

I have this code and would expected a b as Text.

Result: a a -> see screenshot. What am I doing wrong?

import SwiftUI

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(PublishString(string: "a"))
        .environmentObject(PublishString(string: "b"))
    }
}

enter image description here

and ...this works:

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

class PublishString2 : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString2

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

Upvotes: 5

Views: 1554

Answers (2)

Patrick Michiels
Patrick Michiels

Reputation: 509

The accepted answer is perfectly fine and correct and answers the question.

The following is a simple workaround, if you must use two EnvironmentObjects of the same type to be passed around within your app, and stumble upon this question:

You can make a second class that inherits everything from the first class. Therefore you avoid redundancy and can use both EnvironmentObjects separately.

class PublishString : ObservableObject {

    init(string: String) {
        self.string = string
        print(self.string)
    }

    @Published var string : String = "a"
}

class PublishString2 : PublishString {}

struct ContentView: View {

    @EnvironmentObject var text1 : PublishString
    @EnvironmentObject var text2 : PublishString2

    var body: some View {
        VStack {
            Text(text1.string)
            Text(text2.string)
        }
    }
}

instantiation:

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environmentObject(PublishString(string: "a"))
        .environmentObject(PublishString2(string: "b"))
    }
}

Upvotes: 0

Chris
Chris

Reputation: 4391

As noted by Asperi in the comment, SwiftUI identifies Environment Objects by the type (the class definition you have used). It looks for an object of that type and uses the first one it finds.

One option is to have multiple properties on the one object that you can access (this would mean two separate String properties in your case.

Further information is available on the Apple documentation.

Upvotes: 3

Related Questions