web-dev-qa-db-fra.com

SwiftUI - alternative à if let avec une fermeture conditionnelle

J'essaie d'implémenter ce qui suit dans SwiftUI:

struct PersonView: View {

    @State private var age: Int? = 0

    var body: some View {
        VStack {
            Text("Just a test")
            if let self.age > 0 {
                Text("Display Age: \(age)")
            } else {
                Text("Age must be greater than 0!")
            }
        }
    }
}

Mais, dans SwiftUI, if let entraîne l'erreur suivante:

La fermeture contenant l'instruction de flux de contrôle ne peut pas être utilisée avec le générateur de fonctions 'ViewBuilder'

Donc, après avoir fait des recherches sur ce sujet, je suis tombé sur une recommandation d'utiliser .map pour déballer le age facultatif. Ainsi, j'ai modifié le code dans le VStack comme suit:

Text("Just a test")
self.age.map {elem in
    if elem > 0 {
        Text("Display Age: \(elem)")
    } else {
        Text("Age must be greater than 0!")
    }
}

Inclure un conditionnel dans le .map la fermeture, cependant, entraîne les erreurs suivantes sur la ligne appelant VStack:

'(ViewBuilder.Type) -> (C0, C1) -> TupleView <(C0, C1)>' requiert que '()' soit conforme à 'View'

Le type '()' n'est pas conforme au protocole 'View'

Avez-vous des suggestions sur la façon de surmonter le deuxième ensemble d'erreurs? Ou, existe-t-il une autre approche pour déballer les options et les évaluer dans SwiftUI? Vraiment comme SwiftUI mais je ne peux pas croire que le déballage des options ait été un casse-tête!

2
Vee

Pour de tels cas, je préfère l'approche suivante

struct PersonView: View {

    @State private var age: Int? = 0

    var body: some View {
        VStack {
            Text("Just a test")
            AgeText
        }
    }

    private var AgeText: some View {
        if let age = self.age, age > 0 {
            return Text("Display Age: \(age)")
        } else {
            return Text("Age must be greater than 0!")
        }
    }
}
2
Asperi

Vous essayez de faire deux vérifications sur la valeur de l'âge: vous vous assurez d'abord qu'elle n'est pas nil puis vous vérifiez qu'elle est supérieure à 0. Vous pouvez utiliser map pour vous débarrasser du potentiel nil puis un opérateur ternaire pour modifier conditionnellement le texte affiché:

var body: some View {
    VStack {
        Text("Just a test")
        age.map { Text( $0 > 0 ? "Display Age: \($0)" : "Age must be greater than 0!") }
    }
}
3
LuLuGaGa

Vous pouvez refactoriser votre code en quelque chose de plus basique comme l'utilisation d'une fonction:

var body: some View {
    VStack {
        Text("Just a test")
        Text(text(age: age)) // Using the function
    }
}

func text(age: Int?) -> String { // Defining the function
    guard let age = age else { return "Age not found" }
    if age > 0 { return "Display Age: \(age)" }
    else { return "Age must be greater than 0!" }
}

En général, utilisez les fonctions où vous devez nettoyer votre code. J'espère que les futures versions de Swift le supporteront directement comme nous l'attendons.

2
Mojtaba Hosseini