Swift memiliki sintaks deklarasi properti yang sangat mirip dengan C #:
var foo: Int {
get { return getFoo() }
set { setFoo(newValue) }
}
Namun, ia juga memiliki willSet
dan didSet
bertindak. Ini disebut masing-masing sebelum dan sesudah penyetel dipanggil. Apa tujuan mereka, mengingat Anda hanya bisa memiliki kode yang sama di dalam setter?
get
&set
) pada dasarnya memiliki properti yang dihitung berdasarkan properti lain, misalnya mengubah labeltext
menjadi setahunInt
.didSet
&willSet
Adakah untuk mengatakan ... hei nilai ini telah ditetapkan, sekarang mari kita lakukan ini mis. Sumber data kami telah diperbarui ... jadi mari kita memuat kembali tableView sehingga akan termasuk baris baru. Sebagai contoh lain, lihat jawaban dfri tentang cara memanggil delegasi dididSet
Jawaban:
Intinya tampaknya bahwa kadang-kadang, Anda memerlukan properti yang memiliki penyimpanan otomatis dan beberapa perilaku, misalnya untuk memberi tahu objek lain bahwa properti baru saja diubah. Ketika semua yang Anda miliki adalah
get
/set
, Anda perlu bidang lain untuk menyimpan nilainya. DenganwillSet
dandidSet
, Anda dapat mengambil tindakan saat nilainya diubah tanpa perlu bidang lain. Misalnya, dalam contoh itu:myProperty
mencetak nilai lama dan baru setiap kali dimodifikasi. Dengan hanya getter dan setter, saya akan membutuhkan ini sebagai gantinya:Jadi
willSet
dandidSet
mewakili ekonomi beberapa baris, dan lebih sedikit noise dalam daftar bidang.sumber
willSet
dandidSet
tidak dipanggil saat Anda menyetel properti dari dalam metode init seperti yang dicatat Apple:willSet and didSet observers are not called when a property is first initialized. They are only called when the property’s value is set outside of an initialization context.
myArrayProperty.removeAtIndex(myIndex)
... Tidak diharapkan.Pemahaman saya adalah bahwa set dan dapatkan adalah untuk properti yang dihitung (tidak ada dukungan dari properti yang disimpan )
jika Anda berasal dari Objective-C, ingatlah bahwa konvensi penamaan telah berubah. Dalam Swift, variabel iVar atau instance dinamai properti tersimpan
Contoh 1 (properti hanya baca) - dengan peringatan:
Ini akan menghasilkan peringatan karena ini menghasilkan panggilan fungsi rekursif (pengambil panggilan itu sendiri). Peringatan dalam kasus ini adalah "Mencoba untuk memodifikasi 'tes' di dalam pengambil sendiri".
Contoh 2. Bersyarat baca / tulis - dengan peringatan
Masalah serupa - Anda tidak dapat melakukan ini karena memanggil penyetel secara rekursif. Juga, perhatikan kode ini tidak akan mengeluh tentang tidak ada inisialisasi karena tidak ada properti yang disimpan untuk diinisialisasi .
Contoh 3. baca / tulis properti yang dihitung - dengan backing store
Berikut adalah pola yang memungkinkan pengaturan bersyarat dari properti tersimpan aktual
Catatan Data aktual disebut _test (walaupun bisa berupa data atau kombinasi data)
Contoh 4. Menggunakan kemauan dan memang diatur
Di sini kita melihat willSet dan didSet mencegat perubahan pada properti tersimpan aktual. Ini berguna untuk mengirim pemberitahuan, sinkronisasi dll ... (lihat contoh di bawah)
Contoh 5. Contoh Beton - Kontainer ViewController
Perhatikan penggunaan KEDUA properti yang dihitung dan disimpan. Saya telah menggunakan properti yang dihitung untuk mencegah pengaturan nilai yang sama dua kali (untuk menghindari hal-hal buruk terjadi!); Saya telah menggunakan willSet dan didSet untuk meneruskan pemberitahuan ke viewControllers (lihat dokumentasi UIViewController dan info tentang wadah viewController)
Saya harap ini membantu, dan tolong seseorang berteriak jika saya membuat kesalahan di mana saja di sini!
sumber
//I can't see a way to 'stop' the value being set to the same controller - hence the computed property
peringatan menghilang setelah saya menggunakanif let newViewController = _childVC {
bukanif (_childVC) {
get
, saya pikir Anda perlu menambahkanif _childVC == nil { _childVC = something }
lalureturn _childVC
.Ini disebut Pengamat Properti :
Kutipan dari: Apple Inc. “Bahasa Pemrograman Swift.” iBooks. https://itun.es/ca/jEUH0.l
Saya menduga itu untuk memungkinkan hal-hal yang secara tradisional akan kita lakukan dengan KVO seperti pengikatan data dengan elemen UI, atau memicu efek samping dari mengubah properti, memicu proses sinkronisasi, pemrosesan latar belakang, dll, dll.
sumber
sumber
Anda juga dapat menggunakan
didSet
untuk mengatur variabel ke nilai yang berbeda. Ini tidak menyebabkan pengamat dipanggil lagi seperti yang dinyatakan dalam panduan Properti . Misalnya, berguna ketika Anda ingin membatasi nilai seperti di bawah ini:sumber
Banyak jawaban yang sudah ditulis dengan baik mencakup pertanyaan dengan baik, tetapi saya akan menyebutkan, secara rinci, tambahan yang saya yakin layak untuk dibahas.
The
willSet
dandidSet
properti pengamat dapat digunakan untuk menelepon delegasi, misalnya, untuk properti kelas yang hanya pernah diperbarui oleh interaksi pengguna, tetapi di mana Anda ingin menghindari memanggil delegasi di objek inisialisasi.Saya akan mengutip komentar terpilih Klaas untuk jawaban yang diterima:
Ini cukup rapi karena artinya, misalnya,
didSet
properti merupakan pilihan awal yang baik untuk callback & fungsi delegasi, untuk kelas khusus Anda sendiri.Sebagai contoh, pertimbangkan beberapa objek kontrol pengguna kustom, dengan beberapa properti utama
value
(misalnya posisi dalam kontrol peringkat), diimplementasikan sebagai subkelas dariUIView
:Setelah fungsi delegasi Anda dapat digunakan di, katakanlah, beberapa view controller untuk mengamati perubahan kunci dalam model untuk
CustomViewController
, seperti halnya Anda akan menggunakan fungsi delegasi inheren objekUITextFieldDelegate
forUITextField
(misalnyatextFieldDidEndEditing(...)
).Untuk contoh sederhana ini, gunakan panggilan balik delegasi dari
didSet
properti kelasvalue
untuk memberi tahu pengontrol tampilan bahwa salah satu outletnya memiliki pembaruan model yang terkait:Di sini,
value
properti telah dienkapsulasi, tetapi secara umum: dalam situasi seperti ini, berhati-hatilah untuk tidak memperbaruivalue
properticustomUserControl
objek dalam lingkup fungsi delegasi terkait (di sinididChangeValue()
:) di pengontrol tampilan, atau Anda akan berakhir dengan rekursi tak terbatas.sumber
Dan perhatikan bahwa
willSet
perlu nama parameter untuk bekerja, di sisi lain,didSet
tidak.sumber
Getter dan setter terkadang terlalu berat untuk diterapkan hanya untuk mengamati perubahan nilai yang tepat. Biasanya ini membutuhkan penanganan variabel sementara tambahan dan pemeriksaan tambahan, dan Anda akan ingin menghindari bahkan tenaga kerja kecil jika Anda menulis ratusan getter dan setter. Barang-barang ini untuk situasi ini.
sumber
willSet
dandidSet
dibandingkan dengan kode setter yang setara? Ini sepertinya klaim yang berani.Di kelas (basis) Anda sendiri,
willSet
dandidSet
cukup redundan , karena Anda dapat mendefinisikan properti yang dihitung (yaitu metode get dan set) yang mengakses a_propertyVariable
dan melakukan pra-dan pasca-pemrosesan yang diinginkan .Jika, bagaimanapun , Anda menimpa kelas di mana properti tersebut sudah ditetapkan , maka para
willSet
dandidSet
yang berguna dan tidak berlebihan!sumber
Satu hal
didSet
yang sangat berguna adalah ketika Anda menggunakan outlet untuk menambah konfigurasi tambahan.sumber
Saya tidak tahu C #, tetapi dengan sedikit tebakan saya pikir saya mengerti apa
tidak. Itu terlihat sangat mirip dengan apa yang Anda miliki di Swift, tetapi tidak sama: di Swift Anda tidak memiliki
getFoo
dansetFoo
. Itu tidak sedikit perbedaan: itu berarti Anda tidak memiliki penyimpanan yang mendasari untuk nilai Anda.Swift telah menyimpan dan menghitung properti.
Properti yang dikomputasi telah
get
dan mungkin telahset
(jika dapat ditulisi). Tetapi kode dalam pengambil dan penyetel, jika mereka perlu benar-benar menyimpan beberapa data, harus melakukannya di yang lain properti . Tidak ada penyimpanan dukungan.Properti yang disimpan, di sisi lain, memang memiliki penyimpanan dukungan. Tetapi tidak memiliki
get
danset
. Sebaliknya ia memilikiwillSet
dandidSet
yang dapat Anda gunakan untuk mengamati perubahan variabel dan, pada akhirnya, memicu efek samping dan / atau memodifikasi nilai yang disimpan. Anda tidak memilikiwillSet
dandidSet
untuk properti yang dihitung, dan Anda tidak membutuhkannya karena untuk properti yang dihitung Anda dapat menggunakan kodeset
untuk mengontrol perubahan.sumber
getFoo
dansetFoo
adalah penampung sederhana untuk apa pun yang Anda inginkan untuk dilakukan oleh pengambil dan setter. C # tidak membutuhkannya juga. (Saya memang melewatkan beberapa seluk-beluk sintaksis seperti yang saya minta sebelum saya memiliki akses ke kompiler.)