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
dan didSet
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:
pengamat willSet dan didSet tidak dipanggil saat properti pertama kali diinisialisasi. Mereka hanya dipanggil ketika nilai properti diatur di luar konteks inisialisasi.
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 dari UIView
:
// CustomUserControl.swift
protocol CustomUserControlDelegate {
func didChangeValue(value: Int)
// func didChangeValue(newValue: Int, oldValue: Int)
// func didChangeValue(customUserControl: CustomUserControl)
// ... other more sophisticated delegate functions
}
class CustomUserControl: UIView {
// Properties
// ...
private var value = 0 {
didSet {
// Possibly do something ...
// Call delegate.
delegate?.didChangeValue(value)
// delegate?.didChangeValue(value, oldValue: oldValue)
// delegate?.didChangeValue(self)
}
}
var delegate: CustomUserControlDelegate?
// Initialization
required init?(...) {
// Initialise something ...
// E.g. 'value = 1' would not call didSet at this point
}
// ... some methods/actions associated with your user control.
}
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 objek UITextFieldDelegate
for UITextField
(misalnya textFieldDidEndEditing(...)
).
Untuk contoh sederhana ini, gunakan panggilan balik delegasi dari didSet
properti kelas value
untuk memberi tahu pengontrol tampilan bahwa salah satu outletnya memiliki pembaruan model yang terkait:
// ViewController.swift
Import UIKit
// ...
class ViewController: UIViewController, CustomUserControlDelegate {
// Properties
// ...
@IBOutlet weak var customUserControl: CustomUserControl!
override func viewDidLoad() {
super.viewDidLoad()
// ...
// Custom user control, handle through delegate callbacks.
customUserControl = self
}
// ...
// CustomUserControlDelegate
func didChangeValue(value: Int) {
// do some stuff with 'value' ...
}
// func didChangeValue(newValue: Int, oldValue: Int) {
// do some stuff with new as well as old 'value' ...
// custom transitions? :)
//}
//func didChangeValue(customUserControl: CustomUserControl) {
// // Do more advanced stuff ...
//}
}
Di sini, value
properti telah dienkapsulasi, tetapi secara umum: dalam situasi seperti ini, berhati-hatilah untuk tidak memperbarui value
properti customUserControl
objek dalam lingkup fungsi delegasi terkait (di sini didChangeValue()
:) di pengontrol tampilan, atau Anda akan berakhir dengan rekursi tak terbatas.
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