Pertanyaan
Dokumen Apple menetapkan bahwa:
pengamat willSet dan didSet tidak dipanggil saat properti pertama kali diinisialisasi. Mereka hanya dipanggil ketika nilai properti diatur di luar konteks inisialisasi.
Apakah mungkin untuk memaksa ini dipanggil saat inisialisasi?
Mengapa?
Katakanlah saya memiliki kelas ini
class SomeClass {
var someProperty: AnyObject {
didSet {
doStuff()
}
}
init(someProperty: AnyObject) {
self.someProperty = someProperty
doStuff()
}
func doStuff() {
// do stuff now that someProperty is set
}
}
Saya menciptakan metode doStuff
, untuk membuat panggilan pemrosesan lebih ringkas, tetapi saya lebih suka hanya memproses properti dalam didSet
fungsi. Apakah ada cara untuk memaksa panggilan ini saat inisialisasi?
Memperbarui
Saya memutuskan untuk hanya menghapus intializer kenyamanan untuk kelas saya dan memaksa Anda untuk mengatur properti setelah inisialisasi. Ini memungkinkan saya untuk tahu didSet
akan selalu dipanggil. Saya belum memutuskan apakah ini secara keseluruhan lebih baik, tapi itu cocok dengan situasi saya dengan baik.
defer
:convenience init(someProperty: AnyObject) { self.init() defer { self.someProperty = someProperty }
Jawaban:
Buat set-Method sendiri dan gunakan dalam init-Method Anda:
sumber
someProperty
sebagai tipe:AnyObject!
(suatu opsi yang secara implisit tidak terbuka), Anda mengizinkanself
untuk menginisialisasi sepenuhnya tanpasomeProperty
disetel. Saat Anda menelepon,setSomeProperty(someProperty)
Anda menelepon yang setara denganself.setSomeProperty(someProperty)
. Biasanya Anda tidak dapat melakukan ini karenaself
belum sepenuhnya diinisialisasi. KarenasomeProperty
tidak memerlukan inisialisasi dan Anda memanggil metode yang bergantungself
, Swift meninggalkan konteks inisialisasi dandidSet
akan berjalan.init() { *HERE* }
akan didetet dipanggil. Bagus untuk pertanyaan ini tetapi menggunakan fungsi sekunder untuk menetapkan beberapa nilai mengarah ke didSet dipanggil. Tidak bagus jika Anda ingin menggunakan kembali fungsi setter itu.Jika Anda menggunakan
defer
dalam sebuah initializer , untuk memperbarui setiap sifat opsional atau memperbarui lanjut sifat non-opsional yang Anda sudah diinisialisasi dan setelah Anda disebut setiapsuper.init()
metode, maka AndawillSet
,didSet
, dll akan dipanggil. Saya menemukan ini lebih nyaman daripada menerapkan metode terpisah yang Anda harus melacak panggilan di tempat yang tepat.Sebagai contoh:
Akan menghasilkan:
sumber
defer
. Terima kasih.Sebagai variasi jawaban Oliver, Anda bisa membungkus garis dengan penutupan. Misalnya:
Sunting: Jawaban Brian Westphal lebih baik imho. Hal yang baik tentang miliknya adalah bahwa itu mengisyaratkan maksudnya.
sumber
Saya memiliki masalah yang sama dan ini bekerja untuk saya
sumber
Ini berfungsi jika Anda melakukan ini dalam subkelas
Dalam
a
contoh,didSet
tidak dipicu. Tetapi dalamb
contoh,didSet
dipicu, karena itu di dalam subkelas. Itu harus melakukan sesuatu dengan apa yanginitialization context
sebenarnya berarti, dalam hal inisuperclass
memang peduli tentang itusumber
Meskipun ini bukan solusi, cara alternatif untuk melakukannya adalah menggunakan konstruktor kelas:
sumber
someProperty
karena tidak akan memberinya nilai selama inisialisasi.Dalam kasus tertentu di mana Anda ingin meminta
willSet
ataudidSet
di dalaminit
untuk properti yang tersedia di superclass Anda, Anda dapat langsung menetapkan properti super Anda secara langsung:Perhatikan bahwa solusi Charlesism dengan penutupan akan selalu berhasil juga dalam kasus itu. Jadi solusi saya hanyalah sebuah alternatif.
sumber
Anda dapat menyelesaikannya dengan cara obj-с:
sumber
self.someProperty
Anda meninggalkan ruang inisialisasi. Saya percaya hal yang sama dapat dicapai dengan melakukanvar someProperty: AnyObject! = nil { didSet { ... } }
. Namun, beberapa orang mungkin menghargainya sebagai kerja keras, terima kasih untuk penambahannya