web-dev-qa-db-fra.com

Erreur "La fonction déclare un type de retour opaque [...]" lors de la déclaration d'une vue en tant que variable à l'intérieur du corps d'une vue dans SwiftUI

Supposons que j'ai un View avec un Image qui a une propriété shadow:

struct ContentView: View {
    var body: some View {
        Image("turtlerock").shadow(radius: 10)
    }
}

Imaginez maintenant que je souhaite accéder à la valeur du rayon d'ombre. J'ai supposé que je pouvais faire ça:

struct ContentView: View {
    var body: some View {
        let myImage = Image("turtlerock").shadow(radius: 10)
        print(myImage.modifier.radius)
    }
}

Cependant, cela renvoie une erreur:

La fonction déclare un type de retour opaque, mais n'a pas d'instructions de retour dans son corps à partir desquelles déduire un type sous-jacent

Y a-t-il un moyen d'accomplir cela d'une manière ou d'une autre?

16
Tamás Sengel

Lorsque vous modifiez et créez des vues, vous pouvez le faire sans instruction de retour et sans bloc de construction les uns au-dessus des autres sans virgule. C'est ce qu'on appelle une clôture à déclarations multiples. Lorsque vous essayez de créer une variable à l'intérieur d'une fermeture multi-instructions, le compilateur va se plaindre car il y a un décalage dans les types (vous ne pouvez combiner les vues que les unes après les autres, rien de plus ). Voir cette réponse pour plus de détails: https://stackoverflow.com/a/56435128/771525

Un moyen de résoudre ce problème consiste à renvoyer explicitement les vues que vous combinez, afin de ne pas utiliser les instructions de fermeture multiple:

struct MyView: View {
    var body: some View {
        let image = Image("Some image").shadow(radius: 10)
        let myRadius = image.modifier.radius

        // Do something with myRadius

        return image // No multi closure statements.
    }
}
26
J. Doe

Si votre vue que vous souhaitez référencer est à l'intérieur d'une pile, vous devez la déclarer en dehors de la pile comme ceci:

var body: some View {
    let myImage = Image("image").shadow(radius: 10)

    let stack = HStack {
        myImage
        Image("image2")
    }

    return stack
}
3
Tamás Sengel

Vous pouvez définir l'image à l'extérieur du corps:

let myImage = Image("turtlerock").shadow(radius: 10)

var body: some View {
  myImage
}

Pour imprimer le rayon, vous pouvez faire comme ceci:

var body: some View {
  myImage
    .tapAction {
      print(self.myImage.modifier.radius) // 10.0
  }
}

Quand cela m'arrive dans un environnement de test, je niche simplement tout dans le corps à l'intérieur d'un

    return ZStack{ ...}

Un peu rapide et sale, mais cela fonctionne pour mes besoins.

0
jpelayo