Argh ! Tu étais si proche. C'est comme ça que ça se passe. Il vous manque le signe dollar (beta 3) ou le trait de soulignement (beta 4), et soit self devant votre propriété amount, soit .value après le paramètre amount. Toutes ces options fonctionnent :
Vous verrez que j'ai enlevé le @State
en includeDecimal
Vérifiez l'explication à la fin.
C'est l'utilisation de la propriété (mettre self devant) :
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(amount: Binding<Double>) {
// self.$amount = amount // beta 3
self._amount = amount // beta 4
self.includeDecimal = round(self.amount)-self.amount > 0
}
}
ou en utilisant .value après (mais sans self, car vous utilisez le paramètre passé, pas la propriété de la structure) :
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(amount: Binding<Double>) {
// self.$amount = amount // beta 3
self._amount = amount // beta 4
self.includeDecimal = round(amount.value)-amount.value > 0
}
}
C'est la même chose, mais nous utilisons des noms différents pour le paramètre (withAmount) et la propriété (amount), de sorte que vous voyez clairement quand vous utilisez chacun d'eux.
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(withAmount: Binding<Double>) {
// self.$amount = withAmount // beta 3
self._amount = withAmount // beta 4
self.includeDecimal = round(self.amount)-self.amount > 0
}
}
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(withAmount: Binding<Double>) {
// self.$amount = withAmount // beta 3
self._amount = withAmount // beta 4
self.includeDecimal = round(withAmount.value)-withAmount.value > 0
}
}
Notez que .value n'est pas nécessaire avec la propriété, grâce à l'enveloppe de la propriété (@Binding), qui crée les accesseurs qui rendent le .value inutile. Cependant, avec le paramètre, il n'y a pas de telle chose et vous devez le faire explicitement. Si vous souhaitez en savoir plus sur les wrappers de propriétés, consultez la page Session 415 de la WWDC - Conception d'API Swift modernes et sauter à 23:12.
Comme vous l'avez découvert, la modification de la variable @State à partir de l'initialisateur entraînera l'erreur suivante : Thread 1 : Erreur fatale : Accès à l'état en dehors de View.body . Pour l'éviter, vous devez soit supprimer l'@State. Ce qui est logique car includeDecimal n'est pas une source de vérité. Sa valeur est dérivée du montant. En supprimant @State, cependant, includeDecimal
ne sera pas mis à jour si le montant change. Pour cela, la meilleure option est de définir votre includeDecimal comme une propriété calculée, de sorte que sa valeur soit dérivée de la source de vérité (le montant). De cette façon, lorsque le montant change, votre includeDecimal change aussi. Si votre vue dépend de includeDecimal, elle doit être mise à jour lorsqu'elle change :
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal: Bool {
return round(amount)-amount > 0
}
init(withAmount: Binding<Double>) {
self.$amount = withAmount
}
var body: some View { ... }
}
Comme l'indique rob mayoff vous pouvez également utiliser $$varName
(bêta 3), ou _varName
(beta4) pour initialiser une variable d'état :
// Beta 3:
$$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
// Beta 4:
_includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)