web-dev-qa-db-fra.com

Le type de propriété 'Int' ne correspond pas à celui de la propriété 'wrappedValue' de son type de wrapper 'EnvironmentObject'

J'essaie d'utiliser un @EnvironmentObject pour transmettre des données à ma vue SwiftUI:

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)
}

La ligne avec @EnvironmentObject avait une erreur de compilation (répertoriée ci-dessus).

Comment utiliser @EnvironmentObject avec un Int?


Mise à jour: Une pensée était que @EnvironmentObject ne peut être utilisé qu'avec des classes conformes à ObservableObject, j'ai donc essayé de passer à @Environment qui maintenant cette partie compilée, mais a produit une erreur différente:

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)
}

Maintenant, quand j'essaye de le construire, il se plaint que myInt n'est pas défini.

3
Senseful

Si vous souhaitez utiliser le système d'environnement, vous devez fournir une clé pour y accéder. Vous ne pouvez pas utiliser une clé non enregistrée (ce qui est votre erreur). Commencez par créer un EnvironmentKey:

struct MyIntEnvironmentKey: EnvironmentKey {
    static var defaultValue = 0
}

Ensuite, créez un chemin d'accès clé pour définir/obtenir la valeur de votre environnement:

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

Maintenant, vous pouvez le définir dans votre vue parent:

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

Et surtout, vous devez référencer la clé dans la vue dans laquelle vous souhaitez la référencer:

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

    var body: some View {
        Text("\(self.myInt)")
    }
}
3
Procrastin8

@EnvironmentObject peut niquement être utilisé avec un class. Int est en fait un struct.

De plus, cela devrait ressembler davantage à ceci à l'intérieur SceneDelegate.Swift:

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

if let windowScene = /* ... */

Si vous voulez essayer de partager ce Int entre Views, vous pouvez envelopper la valeur dans une classe:

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