Argh! Kamu sangat dekat. Beginilah cara Anda melakukannya. Anda melewatkan tanda dolar (beta 3) atau garis bawah (beta 4), dan diri sendiri di depan properti jumlah Anda, atau .value setelah parameter jumlah. Semua opsi ini berfungsi:
Anda akan melihat bahwa saya menghapus @State
in includeDecimal, periksa penjelasannya di bagian akhir.
Ini menggunakan properti (letakkan diri di depannya):
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
}
}
atau menggunakan .value after (tetapi tanpa self, karena Anda menggunakan parameter yang diteruskan, bukan properti struct):
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
}
}
Ini sama, tetapi kami menggunakan nama yang berbeda untuk parameter (withAmount) dan properti (jumlah), jadi Anda dapat melihat dengan jelas kapan Anda menggunakan masing-masing.
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
}
}
Perhatikan bahwa .value tidak diperlukan dengan properti, berkat pembungkus properti (@Binding), yang membuat pengakses yang membuat .value tidak diperlukan. Namun, dengan parameter, tidak ada hal seperti itu dan Anda harus melakukannya secara eksplisit. Jika Anda ingin mempelajari lebih lanjut tentang pembungkus properti, periksa sesi WWDC 415 - Desain API Swift Modern dan lompat ke 23:12.
Seperti yang Anda temukan, mengubah variabel @State dari initilizer akan memunculkan kesalahan berikut: Thread 1: Kesalahan fatal: Mengakses Status di luar View.body . Untuk menghindarinya, Anda harus menghapus @State. Yang masuk akal karena includeDecimal bukanlah sumber kebenaran. Nilainya berasal dari jumlah. Dengan menghapus @State, bagaimanapun, includeDecimal
tidak akan diperbarui jika jumlahnya berubah. Untuk mencapainya, opsi terbaik adalah dengan mendefinisikan includeDecimal Anda sebagai properti yang dihitung, sehingga nilainya diturunkan dari sumber kebenaran (jumlah). Dengan cara ini, setiap kali jumlahnya berubah, includeDecimal Anda juga. Jika tampilan Anda bergantung pada includeDecimal, itu harus diperbarui ketika berubah:
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 { ... }
}
Seperti yang ditunjukkan oleh rob mayoff , Anda juga dapat menggunakan $$varName
(beta 3), atau _varName
(beta4) untuk menginisialisasi variabel Status :
$$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 > 0
dariThread 1: Fatal error: Accessing State<Bool> outside View.body
@State
variabel harus mewakili sumber kebenaran. Tetapi dalam kasus Anda, Anda menduplikasi kebenaran itu, karena nilai includeDecimal dapat diturunkan dari sumber kebenaran Anda yang sebenarnya yaitu jumlah. Anda memiliki dua opsi: 1. Anda menjadikan includeDecimal var pribadi (tanpa @State), atau bahkan lebih baik 2. Anda menjadikannya properti terhitung yang memperoleh nilainyaamount
. Dengan cara ini, jika jumlahnya berubah,includeDecimal
juga demikian. Anda harus menyatakannya seperti ini:private var includeDecimal: Bool { return round(amount)-amount > 0 }
dan menghapusself.includeDecimal = ...
includeDecimal
jadi saya membutuhkannya sebagai variabel @State dalam tampilan. Saya benar-benar hanya ingin memulainya dengan nilai awal.value
telah diganti dengan.wrappedValue
, alangkah baiknya memperbarui jawaban dan menghapus opsi beta.Anda berkata (dalam komentar) "Saya harus bisa berubah
includeDecimal
". Apa artinya berubahincludeDecimal
? Anda tampaknya ingin menginisialisasi berdasarkan apakahamount
(pada waktu inisialisasi) adalah bilangan bulat. Baik. Jadi apa yang terjadi jikaincludeDecimal
yangfalse
dan kemudian Anda mengubahnya ketrue
? Apakah Anda entah bagaimana akan memaksaamount
menjadi non-integer?Lagi pula, Anda tidak dapat memodifikasi
includeDecimal
diinit
. Tapi Anda bisa memulainyainit
, seperti ini: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
(Perhatikan bahwa di beberapa titik yang
$$includeDecimal
sintaks akan berubah menjadi_includeDecimal
.)sumber
Karena ini pertengahan tahun 2020, mari kita rekap:
Mengenai
@Binding amount
_amount
hanya disarankan untuk digunakan selama inisialisasi. Dan jangan pernah menetapkan seperti iniself.$amount = xxx
selama inisialisasiamount.wrappedValue
danamount.projectedValue
tidak sering digunakan, tetapi Anda dapat melihat kasus seperti@Environment(\.presentationMode) var presentationMode self.presentationMode.wrappedValue.dismiss()
@Binding var showFavorited: Bool Toggle(isOn: $showFavorited) { Text("Change filter") }
sumber