Saya mempelajari pengembangan iOS dari kursus online dan setiap kali saya membuat tampilan kustom (sel tampilan tabel kustom, sel tampilan koleksi, dll.) Instruktur selalu menerapkan penginisialisasi ini:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
Mengapa saya harus selalu menyebutnya demikian? Apa fungsinya? Bisakah saya meletakkan properti di dalam init?
NSCoding
maka Anda perlu mengimplementasikan initialiser ini, karena ini diperlukan untuk class yang mengimplementasikanNSCoding
. Anda setidaknya harus memanggil metode init superclass. JikaNSCoder
berisi properti yang dikodekan untuk kelas Anda maka Anda dapat menggunakan metode ini untuk memulihkannyaJawaban:
Saya akan memulai jawaban ini dari arah yang berlawanan: bagaimana jika Anda ingin menyimpan status tampilan Anda ke disk? Ini dikenal sebagai serialisasi . Kebalikannya adalah deserialization - memulihkan status objek dari disk.
The
NSCoding
protokol mendefinisikan dua metode untuk cerita bersambung dan deserialize objek:Jadi mengapa itu dibutuhkan di kelas khusus Anda? Jawabannya adalah Interface Builder. Saat Anda menyeret objek ke storyboard dan mengonfigurasinya, Pembuat Antarmuka membuat serial status objek tersebut ke disk, lalu deserialisasi saat storyboard muncul di layar. Anda perlu memberi tahu Pembuat Antarmuka cara melakukannya. Paling tidak, jika Anda tidak menambahkan properti baru apa pun ke subkelas Anda, Anda cukup meminta superclass untuk melakukan pengepakan dan pembongkaran untuk Anda, karenanya
super.init(coder: aDecoder)
dipanggil. Jika subclass Anda lebih kompleks, Anda perlu menambahkan kode serialisasi dan deserialisasi Anda sendiri untuk subclass tersebut.Ini berbeda dengan pendekatan Visual Studio, yaitu menulis kode ke dalam file tersembunyi untuk membuat objek pada waktu proses.
sumber
init(coder aCoder : NSCoder)
?awakeFromNib
tidak akan berfungsi.awakeFromNib
dipanggil pada waktu proses . Apa pun yang Anda lakukan di Interface Builder adalah selama waktu desain . Untuk melaksanakan apa yang telah Anda lakukan dalam waktu desain untuk menjalankan waktu adalahencodeWithCoder
(menghemat) daninit(coder:)
(memuat)awakeFromNib
atauinitWIthFrame
Persyaratan untuk mengimplementasikan penginisialisasi tersebut merupakan konsekuensi dari dua hal:
The Liskov prinsip substitusi . Jika S adalah subkelas dari T (misalnya
MyViewController
adalah subkelas dariViewController
), maka objek S (contoh dariMyViewController
) harus dapat diganti di mana objek T (contoh dariViewController
) diharapkan.Penginisialisasi tidak diwarisi di Swift jika penginisialisasi apa pun secara eksplisit ditentukan dalam subkelas. Jika satu penginisialisasi disediakan secara eksplisit, maka semua penginisialisasi lainnya harus disediakan secara eksplisit (yang kemudian dapat dipanggil
super.init(...)
). Lihat pertanyaan ini untuk alasannya. Ada di Jawa, tapi tetap berlaku.Pada poin 1, semua yang asli
ViewController
dapat lakukan,MyViewController
subkelas harus dapat melakukannya. Salah satunya adalah dapat diinisialisasi dari yang diberikanNSCoder
. Pada poin 2,MyViewController
subkelas Anda tidak secara otomatis mewarisi kemampuan ini. Jadi, Anda harus menyediakan penginisialisasi yang memenuhi persyaratan ini secara manual. Dalam hal ini, Anda hanya perlu mendelegasikan ke superclass tersebut, untuk membuatnya melakukan apa yang biasanya dilakukannya.sumber