私はお金の入力画面で作業しており、初期化された金額に基づいて状態変数を設定するためにカスタムinit
を実装する必要があります。
これはうまくいくと思っていましたが、次のコンパイラエラーが発生します。
Cannot assign value of type 'Binding<Double>' to type 'Double'
struct AmountView : View {
@Binding var amount: Double
@State var includeDecimal = false
init(amount: Binding<Double>) {
self.amount = amount
self.includeDecimal = round(amount)-amount > 0
}
...
}
ああ!あなたはとても近かった。これがあなたのやり方です。ドル記号(ベータ3)またはアンダースコア(ベータ4)を逃し、amountプロパティの前にselfを入力したか、amountパラメータの後に.valueを入力しなかった。これらのオプションはすべて機能します。
@State
in includeDecimalを削除したことがわかります。最後の説明を確認してください。
これはプロパティを使用しています(自分の前に自己を置きます):
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
}
}
または、後に.valueを使用します(ただし、構造体のプロパティではなく、渡されたパラメーターを使用しているため、自己なし)。
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
}
}
これは同じですが、パラメータ(withAmount)とプロパティ(amount)に異なる名前を使用しているため、それぞれをいつ使用するかが明確にわかります。
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
}
}
プロパティラッパー(@Binding)のおかげで、プロパティに.valueは不要です。これにより、.valueが不要になるアクセサーが作成されます。ただし、パラメーターではそのようなことはなく、明示的に行う必要があります。プロパティラッパーの詳細については、 WWDCセッション415-Modern Swift API Design を確認して23:12にジャンプしてください。
発見したように、初期化子から@State変数を変更すると、次のエラーがスローされます。スレッド1:致命的なエラー:View.body。これを回避するには、@ Stateを削除する必要があります。 includeDecimalは真実のソースではないため、これは理にかなっています。その値は金額から導出されます。ただし、@ Stateを削除すると、量が変わってもincludeDecimal
は更新されません。これを実現するための最良のオプションは、includeDecimalを計算されたプロパティとして定義し、その値が真のソース(量)から派生するようにすることです。このように、量が変化するたびに、includeDecimalも変化します。ビューがincludeDecimalに依存している場合は、変更時に更新する必要があります。
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 { ... }
}
rob mayoffで示されているように、$$varName
(ベータ3)、または_varName
(beta4)でState変数を初期化します。
// Beta 3:
$$includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
// Beta 4:
_includeDecimal = State(initialValue: (round(amount.value) - amount.value) != 0)
あなたは(コメントで)「私はincludeDecimal
を変更できるようにする必要があります」と言った。 includeDecimal
を変更するとはどういう意味ですか? amount
(初期化時)が整数かどうかに基づいて初期化したいようです。はい。では、includeDecimal
がfalse
で、後でtrue
に変更するとどうなりますか?どうにかしてamount
を非整数に強制しますか?
とにかく、includeDecimal
のinit
を変更することはできません。ただし、次のようにinit
で初期化できます。
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
( ある時点で$$includeDecimal
構文は_includeDecimal
に変更されることに注意してください。)