¡Argh! Estabas tan cerca. Así es como lo haces. Se perdió un signo de dólar (beta 3) o un guión bajo (beta 4), y usted mismo frente a su propiedad de monto, o .value después del parámetro de monto. Todas estas opciones funcionan:
Verá que @Stateeliminé el includeDecimal, verifique la explicación al final.
Esto está usando la propiedad (poner self delante de ella):
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(amount: Binding<Double>) {
self._amount = amount
self.includeDecimal = round(self.amount)-self.amount > 0
}
}
o usando .value después (pero sin self, porque está usando el parámetro pasado, no la propiedad de la estructura):
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(amount: Binding<Double>) {
self._amount = amount
self.includeDecimal = round(amount.value)-amount.value > 0
}
}
Esto es lo mismo, pero usamos diferentes nombres para el parámetro (withAmount) y la propiedad (amount), por lo que puede ver claramente cuándo está usando cada uno.
struct AmountView : View {
@Binding var amount: Double
private var includeDecimal = false
init(withAmount: Binding<Double>) {
self._amount = withAmount
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
self.includeDecimal = round(withAmount.value)-withAmount.value > 0
}
}
Tenga en cuenta que .value no es necesario con la propiedad, gracias al contenedor de propiedades (@Binding), que crea los descriptores de acceso que hacen innecesario el .value. Sin embargo, con el parámetro, no existe tal cosa y hay que hacerlo explícitamente. Si desea obtener más información sobre los envoltorios de propiedades, consulte la sesión 415 de la WWDC: Diseño de API Swift moderno y pase a las 23:12.
Como descubrió, la modificación de la variable @State desde el initilizer arrojará el siguiente error: Subproceso 1: Error fatal: Accediendo al Estado fuera de View.body . Para evitarlo, debe eliminar el @State. Lo cual tiene sentido porque includeDecimal no es una fuente de verdad. Su valor se deriva de la cantidad. Sin embargo, al eliminar @State, includeDecimalno se actualizará si cambia la cantidad. Para lograrlo, la mejor opción es definir su includeDecimal como una propiedad calculada, de modo que su valor se derive de la fuente de verdad (cantidad). De esta manera, siempre que cambie la cantidad, su includeDecimal también lo hará. Si su vista depende de includeDecimal, debería actualizarse cuando cambie:
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 { ... }
}
Como lo indica rob mayoff , también puede usar $$varName(beta 3) o _varName(beta4) para inicializar una variable de estado:
$$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
_includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
self.includeDecimal = round(self.amount)-self.amount > 0deThread 1: Fatal error: Accessing State<Bool> outside View.body@Statelas variables deben representar una fuente de verdad. Pero en su caso, está duplicando esa verdad, porque el valor de includeDecimal puede derivarse de su fuente real de verdad que es la cantidad. Tiene dos opciones: 1. Hace que includeDecimal sea una variable privada (sin @State), o incluso mejor 2. Lo convierte en una propiedad calculada que deriva su valoramount. De esta manera, si la cantidad cambia,includeDecimaltambién lo hace. Debería declararlo así:private var includeDecimal: Bool { return round(amount)-amount > 0 }y eliminar elself.includeDecimal = ...includeDecimalasí que lo necesito como una variable @State en la vista. Realmente solo quiero inicializarlo con un valor inicial.valueha sido reemplazado por.wrappedValue, sería bueno actualizar la respuesta y eliminar las opciones beta.Dijiste (en un comentario) "Necesito poder cambiar
includeDecimal". ¿Qué significa cambiarincludeDecimal? Aparentemente, desea inicializarlo en función de siamount(en el momento de la inicialización) es un número entero. Bueno. Entonces, ¿qué sucede siincludeDecimalesfalsey luego lo cambia atrue? ¿Vas a forzar de alguna maneraamounta ser no entero?De todos modos, no puedes modificar
includeDecimaleninit. Pero puedes inicializarloinit, así:struct ContentView : View { @Binding var amount: Double init(amount: Binding<Double>) { $amount = amount $$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0) } @State private var includeDecimal: Bool(Tenga en cuenta que en algún momento
$$includeDecimalse cambiará la sintaxis_includeDecimal).fuente
Ya que es mediados de 2020, recapitulemos:
En cuanto a
@Binding amount_amountsolo se recomienda su uso durante la inicialización. Y nunca asigne de esta maneraself.$amount = xxxdurante la inicializaciónamount.wrappedValueyamount.projectedValueno se utilizan con frecuencia, pero puede ver casos como@Environment(\.presentationMode) var presentationMode self.presentationMode.wrappedValue.dismiss()@Binding var showFavorited: Bool Toggle(isOn: $showFavorited) { Text("Change filter") }fuente