Dalam WWDC 2014 sesi 403 Intermediate Swift dan transkrip , ada slide berikut
Pembicara mengatakan dalam kasus itu, jika kita tidak menggunakannya di [unowned self]
sana, itu akan menjadi kebocoran memori. Apakah itu berarti kita harus selalu menggunakan [unowned self]
penutupan di dalam?
Pada baris 64 dari ViewController.swift dari aplikasi Swift Weather , saya tidak menggunakan [unowned self]
. Tapi saya memperbarui UI dengan menggunakan beberapa @IBOutlet
s seperti self.temperature
dan self.loadingIndicator
. Mungkin OK karena semua @IBOutlet
yang saya definisikan adalah weak
. Tetapi untuk keamanan, haruskah kita selalu menggunakan [unowned self]
?
class TempNotifier {
var onChange: (Int) -> Void = {_ in }
var currentTemp = 72
init() {
onChange = { [unowned self] temp in
self.currentTemp = temp
}
}
}
swift
automatic-ref-counting
Jake Lin
sumber
sumber
onChange
harusnya merupakan[weak self]
penutupan, karena itu properti publik (internal, tetapi masih), sehingga objek lain bisa mendapatkan dan menyimpan penutupan, menjaga objek TempNotifier tetap ada (tanpa batas waktu jika objek menggunakan tidak melepaskanonChange
penutupan sampai ia melihatTempNotifier
hilang, melalui referensi lemah sendiri keTempNotifier
) . Jikavar onChange …
duluprivate var onChange …
maka[unowned self]
akan benar. Saya tidak 100% yakin akan hal ini; tolong koreksi seseorang jika saya salah.[]
? Saya tidak dapat menemukan penjelasan di dokumen Apple.{}
adalah closure kosong (instance dari closure) sebagai default (tidak melakukan apa-apa),(Int) -> Void
adalah definisi closure.Jawaban:
Tidak, pasti ada saat di mana Anda tidak ingin menggunakannya
[unowned self]
. Kadang-kadang Anda ingin penutup untuk menangkap diri untuk memastikan bahwa itu masih ada pada saat penutupan dipanggil.Contoh: Membuat permintaan jaringan asinkron
Jika Anda membuat permintaan jaringan asynchronous Anda lakukan ingin penutupan untuk mempertahankan
self
ketika selesai permintaan. Objek itu mungkin telah dibatalkan alokasi tetapi Anda masih ingin dapat menangani penyelesaian permintaan.Kapan harus menggunakan
unowned self
atauweak self
Satu-satunya waktu di mana Anda benar-benar ingin menggunakan
[unowned self]
atau[weak self]
ketika Anda akan membuat siklus referensi yang kuat . Siklus referensi yang kuat adalah ketika ada lingkaran kepemilikan di mana objek akhirnya memiliki satu sama lain (mungkin melalui pihak ketiga) dan karena itu mereka tidak akan pernah dapat dialokasikan kembali karena mereka berdua memastikan bahwa satu sama lain tetap ada.Dalam kasus khusus penutupan, Anda hanya perlu menyadari bahwa variabel apa pun yang dirujuk di dalamnya, akan "dimiliki" oleh penutupan. Selama penutupannya ada, benda-benda itu dijamin ada. Satu-satunya cara untuk menghentikan kepemilikan itu, adalah dengan melakukan
[unowned self]
atau[weak self]
. Jadi jika kelas memiliki penutupan, dan penutupan itu menangkap referensi yang kuat untuk kelas itu, maka Anda memiliki siklus referensi yang kuat antara penutupan dan kelas. Ini juga termasuk jika kelas memiliki sesuatu yang memiliki penutupan.Khususnya dalam contoh dari video
Dalam contoh pada slide,
TempNotifier
memiliki penutupan melaluionChange
variabel anggota. Jika mereka tidak menyatakanself
sebagaiunowned
, penutupan juga akan memilikiself
siklus referensi yang kuat.Perbedaan antara
unowned
danweak
Perbedaan antara
unowned
danweak
adalah yangweak
dinyatakan sebagai Opsional sementaraunowned
tidak. Dengan mendeklarasikannyaweak
Anda bisa menangani kasing yang mungkin ada di dalam penutupan di beberapa titik. Jika Anda mencoba mengaksesunowned
variabel yang nihil, itu akan merusak seluruh program. Jadi hanya gunakanunowned
ketika Anda positif bahwa variabel akan selalu ada saat penutupan adasumber
[weak self]
dalam permintaan jaringan yang tidak sinkron, ada di pengontrol tampilan tempat permintaan itu digunakan untuk mengisi tampilan. Jika pengguna mundur, kita tidak perlu lagi mengisi tampilan, kita juga tidak perlu referensi ke pengontrol tampilan.weak
referensi juga diatur kenil
saat objek dialokasikan.unowned
referensi tidak.unowned
digunakan untuknon-Optional
sementaraweak
digunakan untukOptional
jadi kamiself
adalahOptional
ataunon-optional
?Perbarui 11/2016
Saya menulis artikel tentang memperluas jawaban ini (melihat ke SIL untuk memahami apa yang dilakukan ARC), periksa di sini .
Jawaban asli
Jawaban sebelumnya tidak benar-benar memberikan aturan langsung tentang kapan harus menggunakan satu di atas yang lain dan mengapa, jadi izinkan saya menambahkan beberapa hal.
Diskusi yang tidak dimiliki atau lemah bermuara pada pertanyaan tentang masa pakai variabel dan penutupan yang merujuknya.
Skenario
Anda dapat memiliki dua skenario yang mungkin:
Penutupan memiliki masa pakai variabel yang sama, sehingga penutupan hanya dapat dicapai sampai variabel tercapai . Variabel dan penutupan memiliki umur yang sama. Dalam hal ini Anda harus menyatakan referensi sebagai tidak dimiliki . Contoh umum adalah yang
[unowned self]
digunakan dalam banyak contoh penutupan kecil yang melakukan sesuatu dalam konteks orang tua mereka dan bahwa tidak dirujuk di tempat lain tidak hidup lebih lama dari orang tua mereka.Masa penutupan adalah independen dari salah satu variabel, penutupan masih bisa direferensikan ketika variabel tidak dapat dijangkau lagi. Dalam hal ini Anda harus mendeklarasikan referensi sebagai lemah dan memverifikasi itu tidak nol sebelum menggunakannya (jangan paksa membuka). Contoh umum dari ini adalah
[weak delegate]
Anda dapat melihat dalam beberapa contoh penutupan referensi objek delegasi (seumur hidup) yang sama sekali tidak terkait.Penggunaan Aktual
Jadi, mana yang akan / harus Anda benar-benar gunakan sebagian besar waktu?
Mengutip Joe Groff dari twitter :
Anda akan menemukan lebih banyak tentang
*
pekerjaan batin yang tidak dimiliki di sini .*
Biasanya juga disebut sebagai tidak dimiliki (aman) untuk menunjukkan bahwa pemeriksaan runtime (yang menyebabkan crash untuk referensi yang tidak valid) dilakukan sebelum mengakses referensi yang tidak dimiliki.sumber
Saya pikir saya akan menambahkan beberapa contoh nyata khusus untuk pengontrol tampilan. Banyak penjelasan, tidak hanya di sini di Stack Overflow, benar-benar bagus, tapi saya bekerja lebih baik dengan contoh dunia nyata (@drewag memiliki awal yang baik tentang ini):
weak
, karena mereka berumur panjang. Pengontrol tampilan bisa menutup sebelum permintaan selesai sehinggaself
tidak lagi menunjuk ke objek yang valid ketika penutupan dipanggil.Jika Anda memiliki penutupan yang menangani acara pada tombol. Ini bisa terjadi
unowned
karena begitu pengontrol tampilan hilang, tombol dan item lain yangself
dirujuknya hilang pada saat yang sama. Blok penutup juga akan hilang pada saat yang sama.sumber
weak
daripadaunowned
benar?Jika diri bisa nol dalam penutupan gunakan [diri lemah] .
Jika diri tidak akan pernah nol dalam penutupan gunakan [diri yang tidak dimiliki] .
Dokumentasi Apple Swift memiliki bagian yang hebat dengan gambar yang menjelaskan perbedaan antara menggunakan penutupan yang kuat , lemah , dan tidak dimiliki :
https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AutomaticReferenceCounting.html
sumber
Berikut ini adalah kutipan brilian dari Forum Pengembang Apple yang menjelaskan detail lezat:
unowned
vsunowned(safe)
vsunowned(unsafe)
unowned
vs.weak
Pembaruan: Dalam Swift modern secara
weak
internal menggunakan mekanisme yang sama sepertiunowned
halnya . Jadi perbandingan ini tidak benar karena membandingkan Objective-Cweak
dengan Swiftunonwed
.Alasan
Gembira, ya?
sumber
Ada beberapa jawaban bagus di sini. Tetapi perubahan terbaru tentang bagaimana Swift mengimplementasikan referensi yang lemah harus mengubah keputusan penggunaan diri yang lemah setiap orang vs tidak dimiliki sendiri. Sebelumnya, jika Anda membutuhkan kinerja terbaik menggunakan diri yang tidak dimiliki lebih baik daripada diri yang lemah, selama Anda dapat memastikan bahwa diri tidak akan pernah nol, karena mengakses diri yang tidak dimiliki jauh lebih cepat daripada mengakses diri yang lemah.
Tetapi Mike Ash telah mendokumentasikan bagaimana Swift telah memperbarui implementasi vars lemah untuk menggunakan tabel sisi dan bagaimana ini secara substansial meningkatkan kinerja diri yang lemah.
https://mikeash.com/pyblog/friday-qa-2017-09-22-swift-4-weak-references.html
Sekarang karena tidak ada penalti kinerja yang signifikan untuk diri yang lemah, saya percaya kita harus default untuk menggunakannya di masa depan. Keuntungan dari diri yang lemah adalah bahwa ini adalah opsional, yang membuatnya jauh lebih mudah untuk menulis kode yang lebih benar, pada dasarnya alasan Swift adalah bahasa yang hebat. Anda mungkin berpikir Anda tahu situasi mana yang aman untuk penggunaan diri yang tidak dimiliki, tetapi pengalaman saya meninjau banyak kode pengembang lain adalah, sebagian besar tidak. Saya telah memperbaiki banyak crash ketika self yang tidak dimiliki dialokasikan, biasanya dalam situasi di mana utas latar selesai setelah pengontrol dialokasikan.
Bug dan crash adalah bagian pemrograman yang paling memakan waktu, menyakitkan, dan mahal. Lakukan yang terbaik untuk menulis kode yang benar dan hindari. Saya sarankan menjadikannya sebuah peraturan untuk tidak pernah memaksakan pilihan yang terbuka dan tidak pernah menggunakan diri yang tidak dimiliki, bukannya diri yang lemah. Anda tidak akan kehilangan sesuatu yang hilang saat paksa membuka dan diri yang tidak dimiliki sebenarnya aman. Tetapi Anda akan mendapatkan banyak dari menghilangkan sulit untuk menemukan dan men-debug crash dan bug.
sumber
weak
tidak dapat digunakan sebagai penggantiunowned
?Menurut Apple-doc
Contoh -
sumber
Jika tidak ada satu pun di atas yang masuk akal:
tl; dr
Penjelasan:
Saya mengambil yang berikut di bawah ini di: tautan tidak dimiliki lemah . Dari apa yang saya kumpulkan, diri yang tidak dimiliki tidak mungkin nol, tetapi diri yang lemah bisa, dan diri yang tidak memiliki kepemilikan dapat menyebabkan petunjuk yang menggantung ... sesuatu yang terkenal di Objective-C. Semoga ini bisa membantu
Referensi yang tidak dimiliki , seperti referensi yang lemah, jangan menambah jumlah retensi objek yang dirujuk. Namun, di Swift, referensi yang tidak dimiliki memiliki manfaat tambahan karena tidak menjadi Opsional . Ini membuat mereka lebih mudah dikelola daripada menggunakan pengikatan opsional. Ini tidak seperti Opsional yang Tidak Dibungkus Secara implisit. Selain itu, referensi yang tidak dimiliki adalah non-zeroing . Ini berarti bahwa ketika objek dideallocated, itu tidak nol pointer. Ini berarti bahwa penggunaan referensi yang tidak dimiliki dapat, dalam beberapa kasus, mengarah pada petunjuk menggantung. Untuk Anda para kutu buku di luar sana yang mengingat hari Objective-C seperti yang saya lakukan, referensi yang tidak dimiliki memetakan ke referensi yang tidak aman.
Di sinilah agak membingungkan.
Keduanya dapat digunakan untuk memutus siklus penahan. Jadi kapan kita menggunakannya ?!
Menurut dokumen Apple :
sumber
sumber