Bagaimana cara mengganti referensi yang lemah saat menggunakan ARC dan menargetkan iOS 4.0?

87

Saya mulai mengembangkan aplikasi iOS pertama saya dengan Xcode 4.2, dan menargetkan iOS 5.0 dengan template "aplikasi utilitas" (yang disertakan dengan FlipsideViewController).

Saya membaca bahwa karena ARC adalah fitur waktu kompilasi, itu harus kompatibel dengan iOS 4 juga, jadi saya mencoba menargetkan aplikasi saya ke 4.3, dan mencoba mengompilasinya. Ketika saya melakukannya, saya mendapatkan kesalahan ini:

FlipsideViewController.m: error: Masalah Penghitungan Referensi Otomatis: Target penerapan saat ini tidak mendukung referensi __weak otomatis

Ini merujuk pada baris ini:

@synthesize delegate = _delegate;

Variabel itu dideklarasikan sebagai:

@property (weak, nonatomic) IBOutlet id <FlipsideViewControllerDelegate> delegate;

Saya memahami bahwa "referensi lemah" tidak didukung di iOS 4, tetapi saya tidak begitu mengerti mengapa saya ingin menggunakan referensi yang lemah sebagai permulaan, saya juga tidak tahu bagaimana saya akan menulis ulang hal-hal untuk menghindari penggunaannya, sementara masih memanfaatkan ARC (lagipula, ini seharusnya bekerja dengan iOS 4 DAN 5 kan?)

Mason G. Zhwiti
sumber

Jawaban:

149

Untuk menargetkan OS yang lebih lama, Anda dapat menggunakan unsafe_unretainedsebagai ganti weakdi deklarasi properti Anda, dan sebagian besar berfungsi dengan cara yang sama. weakmereferensikan nol sendiri ketika target mereka hilang, tetapi unsafe_unretainedmembiarkan kemungkinan bahwa objek yang Anda tautkan dapat berubah menjadi penunjuk yang menggantung ketika dialokasikan. Yang terakhir adalah perilaku yang sama seperti jika Anda telah digunakan assignsebagai deklarasi properti dalam manajemen memori manual.

Anda melakukan ini untuk menghindari siklus penahanan, yang saya sebutkan dalam jawaban saya di sini . Anda tidak ingin memiliki penunjuk yang kuat ke sesuatu yang mungkin memiliki penunjuk yang kuat kembali ke objek aslinya. Maka tidak ada yang akan dirilis dengan benar.

Brad Larson
sumber
Terima kasih atas sarannya. Anda mengatakan "untuk menargetkan OS yang lebih lama ...". Apakah ini berarti saya hanya boleh menggunakan unsafe_unretained dalam build aplikasi yang lebih lama dari 5.0? Atau dapatkah saya menggunakan unsafe_unretained dalam kode saya, dan membuatnya untuk menargetkan 4.x dan 5.x?
Mason G.Zhwiti
1
@Mason - unsafe_unretaineddidukung di iOS 4.x dan 5.0, jadi ini memberi Anda kompatibilitas mundur. Jika Anda melakukan build 5.0 saja, Anda dapat beralih ke weakuntuk memanfaatkan keamanan tambahan yang diberikannya kepada Anda.
Brad Larson
Saya mencoba unsafe_unretained, tetap berhasil. Namun, saya mendapat banyak peringatan seperti '"** __NSAutoreleaseNoPool (): Object 0x564bd90 dari kelas __NSArrayM dirilis otomatis tanpa pool di tempatnya - hanya bocor" *', apakah itu normal?
kelima
1
@ Kelima - Itu masalah yang sama sekali tidak terkait. Anda menjalankan sesuatu di thread latar belakang tanpa memiliki kumpulan peluncuran otomatis. Untaian yang dibuat secara manual tidak memiliki kumpulan rilis otomatisnya sendiri, jadi Anda perlu membuatnya sendiri menggunakan @autoreleasepool(di bawah ARC, NSAutoreleasePool untuk implementasi terhitung referensi manual yang lebih lama).
Brad Larson
@Brad, itu membantu, peringatan hilang, saya mendapat beberapa panggilan performSelectorInBackground.
kelima
11

Jika hanya menggunakan referensi yang lemah untuk keamanan tambahan, panggil fungsi runtime baru secara manual jika tersedia dan kembali ke penetapan sederhana pada __unsafe_unretainedvariabel jika tidak.

ZWRCompatibility.h akan menyederhanakan ini.

rpetrich.dll
sumber
10

Berkat pustaka kompatibilitas Mike Ash PLWeakCompatibilty , Anda sekarang dapat menggunakan __weak di iOS 4.x juga.

Ini sangat mudah untuk dikonfigurasi dan tidak memerlukan pertimbangan atau usaha tambahan lebih dari 5.x.

nschum
sumber