Saya ingin menyimpan sejumlah referensi lemah di Swift. Array itu sendiri seharusnya tidak menjadi referensi yang lemah - elemen-elemennya seharusnya. Saya pikir Cocoa NSPointerArray
menawarkan versi yang tidak aman untuk ini.
179
Saya ingin menyimpan sejumlah referensi lemah di Swift. Array itu sendiri seharusnya tidak menjadi referensi yang lemah - elemen-elemennya seharusnya. Saya pikir Cocoa NSPointerArray
menawarkan versi yang tidak aman untuk ini.
Jawaban:
Buat pembungkus generik sebagai:
Tambahkan instance kelas ini ke array Anda.
Saat mendefinisikan,
Weak
Anda dapat menggunakan salah satustruct
atauclass
.Juga, untuk membantu menuai konten array, Anda dapat melakukan sesuatu di sepanjang baris:
Penggunaan di
AnyObject
atas harus diganti denganT
- tapi saya tidak berpikir bahasa Swift saat ini memungkinkan ekstensi yang ditentukan.sumber
Stuff
dengan protokol; lihat pertanyaan terkait iniAnda dapat menggunakan NSHashTable dengan lemahObjectsHashTable.
NSHashTable<ObjectType>.weakObjectsHashTable()
Untuk Swift 3:
NSHashTable<ObjectType>.weakObjects()
Referensi Kelas NSHashTable
sumber
Any
tetapi tidakAnyObject
, seperti protokol.MyProtocol: class
danNSHashTable<MyProtocol>.weakObjects()
. "'NSHashTable' mengharuskan 'MyProtocol' menjadi tipe kelas.Agak terlambat untuk pesta, tapi coba milikku. Saya menerapkan sebagai Set bukan Array.
WeakObjectSet
Pemakaian
Berhati-hatilah bahwa WeakObjectSet tidak akan mengambil tipe String selain NSString. Karena, tipe String bukan jenis apa pun. Versi cepat saya adalah
Apple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
.Kode dapat diambil dari Gist. https://gist.github.com/codelynx/30d3c42a833321f17d39
** DITAMBAH DALAM NOVEMBER.2017
Saya memperbarui kode ke Swift 4
Seperti yang disebutkan gokeji, saya tahu NSString tidak akan dibatalkan alokasi berdasarkan kode yang digunakan. Saya menggaruk kepala dan menulis kelas MyString sebagai berikut.
Lalu gantikan
NSString
denganMyString
seperti ini. Kemudian aneh untuk mengatakan itu berhasil.Kemudian saya menemukan halaman aneh yang mungkin terkait dengan masalah ini.
https://bugs.swift.org/browse/SR-5511
Dikatakan masalahnya
RESOLVED
tetapi saya bertanya-tanya apakah ini masih terkait dengan masalah ini. Bagaimanapun, perbedaan Perilaku antara MyString atau NSString berada di luar konteks ini, tapi saya akan sangat menghargai jika seseorang menemukan masalah ini.sumber
nil
nilai dari internalSet
. Jadi saya telah menambahkanreap()
fungsi yang disebutkan dalam jawaban atas, dan memastikan untuk meneleponreap()
setiap kaliWeakObjectSet
diakses.nil
lagiNSString
tidak.UnsafeMutablePointer<T>(&object)
dapat berubah secara acak (sama denganwithUnsafePointer
). Saya sekarang menggunakan versi yang didukung olehNSHashTable
: gist.github.com/simonseyer/cf73e733355501405982042f760d2a7d .Ini bukan solusi saya. Saya menemukannya di Forum Pengembang Apple .
@GoZoner memiliki jawaban yang bagus, tetapi itu merusak kompiler Swift.
Berikut ini versi dari wadah objek lemah yang tidak merusak kompiler yang dirilis saat ini.
Anda kemudian dapat membuat array dari kontainer ini:
sumber
EXC_BAD_ACCESS
untuk saya. Dengan kelas bekerja dengan baikAnda dapat melakukan ini dengan membuat objek pembungkus untuk memegang pointer lemah.
Dan kemudian menggunakan ini dalam array
sumber
class
menggunakanweak
varsprotocol Protocol : class { ... }
Bagaimana dengan pembungkus gaya fungsional?
Panggil saja penutupan kembali untuk memeriksa target masih hidup.
Dan Anda bisa menyimpan penutupan ini ke dalam array.
Dan Anda dapat mengambil nilai yang ditangkap dengan lemah dengan memetakan pemetaan penutupan.
Sebenarnya, Anda tidak perlu fungsi untuk membuat penutupan. Hanya menangkap objek secara langsung.
sumber
var array: [(x: Int, y: () -> T?)]
. Persis, apa yang saya cari.let values = Array(array1.map({ $0() })) part
. Karena ini bukan lagi array penutupan dengan referensi yang lemah, nilai akan dipertahankan hingga array ini tidak dialokasikan. Jika saya benar maka penting untuk dicatat bahwa Anda tidak boleh mempertahankan array ini sepertiself.items = Array(array1.map({ $0() }))
ini mengalahkan tujuannya.Saya memiliki ide yang sama untuk membuat wadah yang lemah dengan obat generik.
Sebagai hasilnya saya membuat pembungkus untuk
NSHashTable
:Pemakaian:
Ini bukan solusi terbaik, karena
WeakSet
dapat diinisialisasi dengan jenis apa pun, dan jika jenis ini tidak sesuai denganAnyObject
protokol maka aplikasi akan macet dengan alasan terperinci. Tapi saya tidak melihat solusi yang lebih baik saat ini.Solusi asli adalah mendefinisikan
WeakSet
dengan cara ini:Tetapi dalam kasus
WeakSet
ini tidak dapat diinisialisasi dengan protokol:Saat ini kode di atas tidak dapat dikompilasi (Swift 2.1, Xcode 7.1).
Itu sebabnya saya turun menyesuaikan diri
AnyObject
dan menambahkan penjaga tambahan denganfatalError()
penegasan.sumber
Detail
Larutan
Pilihan 1
Opsi 1 penggunaan
pilihan 2
Opsi 2 penggunaan
Sampel lengkap
sumber
protocol TP: class { } class TC { var a = WeakArray<TP>() var b = WeakObjectsArray<TP>() }
protocol TP: class { } class TC<TYPE> where TYPE: TP { var a = WeakObjectsArray<TYPE>() // Use like regular array. With any objects var weakObjectsArray = [TYPE?]() }
delegates
. Maka Anda akan memiliki beberapa pengontrol tampilan yang ingin menggunakan fungsi ini. Anda akan meneleponMyManager.delegates.append(self)
. Tetapi jikaMyManager
dikunci ke beberapa jenis generik maka ini tidak terlalu berguna.protocol TP: class { } class MyManager { typealias Delegate = AnyObject & TP static var delegates = [Delegate?]() } class A: TP { } class B: TP { } //MyManager.delegates.append(A()) //MyManager.delegates.append(B())
Contoh WeakContainer yang ada sangat membantu, tetapi itu tidak benar-benar membantu seseorang menggunakan referensi yang lemah dalam wadah cepat yang ada seperti Daftar dan Kamus.
Jika Anda ingin menggunakan metode Daftar seperti berisi, maka WeakContainer perlu mengimplementasikan Equatable. Jadi saya menambahkan kode untuk memungkinkan WeakContainer menjadi setara.
Jika Anda ingin menggunakan WeakContainer dalam kamus, saya juga membuatnya menjadi hashable sehingga dapat digunakan sebagai kunci kamus.
Saya juga menamainya menjadi WeakObject untuk menekankan bahwa ini hanya untuk tipe kelas dan untuk membedakannya dari contoh WeakContainer:
Ini memungkinkan Anda melakukan beberapa hal keren seperti menggunakan Kamus referensi lemah:
sumber
Berikut adalah cara untuk membuat @ jawaban yang bagus GoZoner ini sesuai dengan
Hashable
, sehingga dapat terindeks di Kontainer benda seperti:Set
,Dictionary
,Array
, dllsumber
Karena
NSPointerArray
sudah menangani sebagian besar dari ini secara otomatis, saya memecahkan masalah dengan membuat pembungkus yang aman untuknya, yang menghindari banyak boilerplate dalam jawaban lain:Contoh penggunaan:
Ini lebih berfungsi di muka, tetapi penggunaan di sisa kode Anda jauh lebih bersih IMO. Jika Anda ingin membuatnya lebih seperti array, Anda bahkan dapat mengimplementasikan subskript, membuatnya menjadi
SequenceType
, dll. (Tetapi proyek saya hanya perluappend
danforEach
jadi saya tidak memiliki kode yang tepat).sumber
Namun solusi lain untuk masalah yang sama ... fokus yang satu ini adalah menyimpan referensi yang lemah ke suatu objek tetapi memungkinkan Anda untuk menyimpan struct juga.
[Saya tidak yakin seberapa berguna itu, tetapi butuh beberapa saat untuk mendapatkan sintaks yang benar]
sumber
Anda dapat membuat pembungkus
Array
. Atau gunakan pustaka ini https://github.com/NickRybalko/WeakPointerArraylet array = WeakPointerArray<AnyObject>()
Ini adalah tipe aman.sumber
Jawaban lain telah membahas sudut generik. Kupikir aku akan membagikan beberapa kode sederhana yang menutupi
nil
sudut.Saya ingin array statis (baca sesekali) dari semua
Label
yang saat ini ada di aplikasi, tetapi tidak ingin melihatnil
di mana yang lama dulu.Tidak ada yang mewah, ini kode saya ...
sumber
flatMap
alih-alihfilter
&map
?Saya mendasarkan ini pada pekerjaan @Eonil, karena saya menyukai strategi penutupan yang lemah, tetapi saya tidak ingin menggunakan operator fungsi untuk suatu variabel, karena rasanya sangat berlawanan dengan intuisi
Apa yang saya lakukan adalah sebagai berikut:
Dengan cara ini Anda dapat melakukan sesuatu seperti:
sumber
Ini solusi saya:
-
sumber
Ini adalah jenis koleksi aman yang menampung wadah benda lemah. Itu juga otomatis menghapus nil wadah / pembungkus ketika diakses.
Contoh:
Koleksi khusus https://gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc
sumber
Bagaimana dengan pendekatan fungsional ?
Ini adalah ide utama, lalu tambahkan logika kenyamanan apa pun untuk melacak apa yang ada dalam array. Misalnya, seseorang dapat mempertimbangkan pendekatan yang sama dengan Kamus menggunakan kunci sebagai cara menemukan apa yang ada di sana.
sumber