Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Property type 'Int' does not match that of the 'wrappedValue' property of its wrapper type 'EnvironmentObject'

I'm trying to use an @EnvironmentObject to pass data to my SwiftUI view:

struct MyView: View {
    @EnvironmentObject var myInt: Int // ❌ Property type 'Int' does not match that of the 'wrappedValue' property of its wrapper type 'EnvironmentObject'

    var body: some View {
        EmptyView()
    }
}
func constructView() {
    let myInt = 1
    MyView()
        .environmentObject(myInt)
}

The line with @EnvironmentObject had a compiler error (listed above).

How do I use @EnvironmentObject with an Int?


Update: One thought was that @EnvironmentObject can only be used with classes that conform to ObservableObject, so I tried switching to @Environment which now that part compiled, but produced a different error:

struct MyView: View {
    @Environment var myInt: Int

    var body: some View {
        EmptyView()
    }
}
func constructView() {
    let myInt = 1
    MyView() // ❌ Missing argument for parameter 'myInt' in call
        .environment(\.myInt, myInt)
}

Now when I attempt to construct it, it complains that myInt isn't set.

like image 239
Senseful Avatar asked Dec 15 '19 22:12

Senseful


2 Answers

@EnvironmentObject can only be used with a class. Int is actually a struct.

If you did want to try to share that Int between Views, you could wrap the value in a class:

class SharedInt: ObservableObject {
    @Published var myInt = 1
}

Also, it should look more like this inside SceneDelegate.swift:

let contentView = ContentView().environmentObject(SharedInt())

if let windowScene = /* ... */

Or in SwiftUI lifecycle's ...App.swift:

WindowGroup {
    ContentView()
        .environmentObject(SharedInt())
}
like image 59
George Avatar answered Nov 13 '22 19:11

George


If you want to use the environment system, you need to provide a key to access it. You can't use an unregistered key (which is what your error is). First, create an EnvironmentKey:

struct MyIntEnvironmentKey: EnvironmentKey {
    static var defaultValue = 0
}

Next, create a key path to set/get your environment value:

extension EnvironmentValues {
    var myInt: Int {
        get { self[MyIntEnvironmentKey.self] }
        set { self[MyIntEnvironmentKey.self] = newValue }
    }
}

Now, you can set it in your parent View:

MyView().environment(\.myInt, myInt)

And crucially, you need to reference the key in the view in which you want to reference it:

struct MyView: View {
    @Environment(\.myInt) private var myInt: Int

    var body: some View {
        Text("\(self.myInt)")
    }
}
like image 44
Procrastin8 Avatar answered Nov 13 '22 18:11

Procrastin8