weak
referensi tampaknya tidak berfungsi di Swift kecuali protocol
dinyatakan sebagai @objc
, yang saya tidak inginkan dalam aplikasi Swift murni.
Kode ini memberikan kesalahan kompilasi ( weak
tidak dapat diterapkan ke tipe non-kelas MyClassDelegate
):
class MyClass {
weak var delegate: MyClassDelegate?
}
protocol MyClassDelegate {
}
Saya perlu awalan protokol dengan @objc
, lalu berfungsi.
Pertanyaan: Apa cara Swift 'murni' untuk mencapai a weak
delegate
?
Jawaban:
Anda perlu mendeklarasikan jenis protokol sebagai
AnyObject
.Menggunakan
AnyObject
Anda mengatakan bahwa hanya kelas yang dapat memenuhi protokol ini, sedangkan struct atau enum tidak bisa.sumber
protocol ProtocolNameDelegate: AnyObject
, tetapi tidak masalah.AnyObject
sejakclass
akan ditinggalkan pada beberapa titik.Jawaban Tambahan
Saya selalu bingung tentang apakah delegasi harus lemah atau tidak. Baru-baru ini saya telah belajar lebih banyak tentang delegasi dan kapan harus menggunakan referensi yang lemah, jadi izinkan saya menambahkan beberapa poin tambahan di sini demi pemirsa di masa depan.
Tujuan menggunakan
weak
kata kunci adalah untuk menghindari siklus referensi yang kuat (mempertahankan siklus). Siklus referensi yang kuat terjadi ketika dua instance kelas memiliki referensi kuat satu sama lain. Jumlah referensi mereka tidak pernah menjadi nol sehingga mereka tidak pernah dibatalkan alokasi.Anda hanya perlu menggunakan
weak
jika delegasi adalah kelas. Struct cepat dan enum adalah tipe nilai (nilainya disalin ketika instance baru dibuat), bukan tipe referensi, sehingga mereka tidak membuat siklus referensi yang kuat .weak
referensi selalu opsional (jika tidak, Anda akan menggunakanunowned
) dan selalu menggunakanvar
(tidaklet
) sehingga opsional dapat diatur kenil
saat itu dialokasikan.Kelas induk harus secara alami memiliki referensi yang kuat untuk kelas anaknya dan karenanya tidak menggunakan
weak
kata kunci. Ketika seorang anak ingin referensi ke orang tuanya, itu harus membuatnya menjadi referensi yang lemah dengan menggunakanweak
kata kunci.weak
harus digunakan ketika Anda ingin referensi ke kelas yang tidak Anda miliki, bukan hanya untuk anak yang mereferensikan orang tuanya. Ketika dua kelas non-hirarkis perlu saling referensi, pilih satu untuk menjadi lemah. Yang Anda pilih tergantung pada situasinya. Lihat jawaban untuk pertanyaan ini untuk lebih lanjut tentang ini.Sebagai aturan umum, delegasi harus ditandai
weak
karena kebanyakan delegasi merujuk kelas yang tidak mereka miliki. Ini benar ketika seorang anak menggunakan delegasi untuk berkomunikasi dengan orang tua. Menggunakan referensi yang lemah untuk delegasi adalah apa yang direkomendasikan oleh dokumentasi . (Tapi lihat ini juga.)Protokol dapat digunakan untuk tipe referensi (kelas) dan tipe nilai (struct, enums). Jadi, jika Anda perlu membuat delegasi lemah, Anda harus menjadikannya hanya protokol objek. Cara untuk melakukannya adalah dengan menambahkan
AnyObject
ke daftar warisan protokol. (Di masa lalu Anda melakukan ini menggunakanclass
kata kunci, tetapiAnyObject
lebih disukai sekarang .)Pelajaran lanjutan
Membaca artikel-artikel berikut adalah yang membantu saya untuk memahami hal ini dengan lebih baik. Mereka juga membahas masalah terkait seperti
unowned
kata kunci dan siklus referensi kuat yang terjadi dengan penutupan.Terkait
sumber
AnyObject
adalah cara resmi untuk menggunakan referensi yang lemah di Swift.Dari Apple:
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID276
sumber
class
usang dalam Swift 4.1?Pembaruan: Sepertinya manual telah diperbarui dan contoh yang saya maksud telah dihapus. Lihat jawaban edit ke @ flainez di atas.
Asli: Menggunakan @objc adalah cara yang tepat untuk melakukannya bahkan jika Anda tidak beroperasi dengan Obj-C. Ini memastikan bahwa protokol Anda diterapkan ke kelas dan bukan enum atau struct. Lihat "Memeriksa Kesesuaian Protokol" dalam manual.
sumber
protokol harus subkelas dari AnyObject, kelas
contoh yang diberikan di bawah ini
sumber
Apple menggunakan "NSObjectProtocol" alih-alih "kelas".
Ini juga berfungsi untuk saya dan menghapus kesalahan yang saya lihat ketika mencoba menerapkan pola delegasi saya sendiri.
sumber