Saya mencoba menyelesaikan teka-teki.
__strong
adalah default untuk semua penunjuk objek yang dapat dipertahankan Objective-C seperti NSObject, NSString, dll. Ini adalah referensi yang kuat. ARC menyeimbangkannya dengan a -release
di akhir ruang lingkup.
__unsafe_unretained
sama dengan cara lama. Ini digunakan untuk penunjuk yang lemah tanpa mempertahankan objek yang dapat dipertahankan.
__weak
seperti __unsafe_unretained
kecuali bahwa itu adalah referensi lemah auto-zeroing yang berarti bahwa penunjuk akan disetel ke nol segera setelah objek yang direferensikan dibatalkan alokasinya. Ini menghilangkan bahaya petunjuk yang menggantung dan kesalahan EXC_BAD_ACCESS.
Tapi sebenarnya __autoreleasing
bagus untuk apa? Saya kesulitan menemukan contoh praktis tentang kapan saya perlu menggunakan kualifikasi ini. Saya percaya itu hanya untuk fungsi dan metode yang mengharapkan pointer-pointer seperti:
- (BOOL)save:(NSError**);
atau
NSError *error = nil;
[database save:&error];
yang di bawah ARC harus dinyatakan seperti ini:
- (BOOL)save:(NSError* __autoreleasing *);
Tapi ini terlalu kabur dan saya ingin memahami alasannya . Potongan kode yang saya temukan menempatkan __autoreleasing di antara dua bintang, yang terlihat aneh bagi saya. NSError**
Jenisnya adalah (pointer-pointer ke NSError), jadi mengapa menempatkan di __autoreleasing
antara bintang-bintang dan tidak hanya di depan NSError**
?
Juga, mungkin ada situasi lain yang harus saya andalkan __autoreleasing
.
sumber
Jawaban:
Kamu benar. Seperti yang dijelaskan dalam dokumentasi resmi:
Semua ini dijelaskan dengan sangat baik dalam panduan transisi ARC .
Dalam contoh NSError Anda, deklarasi tersebut berarti
__strong
, secara implisit:Akan diubah menjadi:
Saat Anda memanggil
save
metode Anda :Kompilator kemudian harus membuat variabel sementara, disetel ke
__autoreleasing
. Begitu:Akan diubah menjadi:
Anda dapat menghindari ini dengan mendeklarasikan objek kesalahan sebagai
__autoreleasing
, secara langsung.sumber
__autoreleasing
hanya digunakan untuk argumen yang diteruskan oleh referensi. Ini adalah kasus khusus, karena Anda memiliki penunjuk ke penunjuk objek. Itu tidak terjadi dengan hal-hal seperti konstruktor praktis, karena mereka hanya mengembalikan pointer ke objek, dan karena ARC menanganinya secara otomatis.Menindaklanjuti jawaban Macmade dan pertanyaan lanjutan Anggota Bangga di komentar, (juga akan memposting ini sebagai komentar tetapi melebihi jumlah karakter maksimal):
Inilah alasan mengapa variabel qualifier __autoreleasing ditempatkan di antara dua bintang.
Sebagai pengantar, sintaks yang benar untuk mendeklarasikan pointer objek dengan qualifier adalah:
Kompiler akan memaafkan ini:
tapi itu tidak benar. Lihat panduan transisi ARC Apple (baca bagian yang memulai "Anda harus menghias variabel dengan benar ...").
Untuk menjawab pertanyaan yang ada: Penunjuk ganda tidak dapat memiliki kualifikasi manajemen memori ARC karena penunjuk yang menunjuk ke alamat memori adalah penunjuk ke tipe primitif, bukan penunjuk ke objek. Namun, saat Anda mendeklarasikan penunjuk ganda, ARC ingin mengetahui apa aturan manajemen memori untuk penunjuk kedua. Itulah mengapa variabel penunjuk ganda ditentukan sebagai:
Jadi dalam kasus argumen metode yang merupakan penunjuk NSError ganda, tipe datanya dideklarasikan sebagai:
yang dalam bahasa Inggris mengatakan "penunjuk ke __autoreleasing penunjuk objek NSError".
sumber
The definitif ARC spesifikasi mengatakan bahwa
Jadi misalnya kodenya
sebenarnya akan diubah menjadi
... itulah sebabnya ini berfungsi ketika Anda memiliki parameter
NSError* __autoreleasing * errorPointer
, metode yang dipanggil kemudian akan menetapkan kesalahan*errorPointer
dan semantik di atas akan dimulai.Anda dapat menggunakan
__autoreleasing
dalam konteks yang berbeda untuk memaksa objek ARC ke dalam kumpulan autorelease, tetapi itu tidak terlalu berguna karena ARC sepertinya hanya menggunakan kumpulan autorelease pada metode return dan sudah menanganinya secara otomatis.sumber