Dalam kode yang diaktifkan ARC, bagaimana cara memperbaiki peringatan tentang siklus mempertahankan potensial, ketika menggunakan API berbasis blok?
Peringatan:
Capturing 'request' strongly in this block is likely to lead to a retain cycle
dihasilkan oleh cuplikan kode ini:
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:...
[request setCompletionBlock:^{
NSDictionary *jsonDictionary = [[CJSONDeserializer deserializer] deserialize:request.rawResponseData error:nil];
// ...
}];
Peringatan terkait dengan penggunaan objek request
di dalam blok.
responseData
alih-alihrawResponseData
, periksa dokumentasi ASIHTTPRequest.Jawaban:
Membalas diri sendiri:
Pemahaman saya tentang dokumentasi mengatakan bahwa menggunakan kata kunci
block
dan mengatur variabel ke nol setelah menggunakannya di dalam blok seharusnya ok, tetapi masih menunjukkan peringatan.Pembaruan: membuatnya berfungsi dengan kata kunci '_ lemah' alih-alih ' _block', dan menggunakan variabel sementara:
Jika Anda juga ingin menargetkan iOS 4, gunakan
__unsafe_unretained
sebagai ganti__weak
. Perilaku yang sama, tetapi pointer tetap menggantung bukannya secara otomatis diatur ke nol ketika objek dihancurkan.sumber
Masalah terjadi karena Anda menetapkan blok untuk meminta yang memiliki referensi kuat untuk meminta di dalamnya. Blokir akan secara otomatis mempertahankan permintaan, sehingga permintaan asli tidak akan membatalkan alokasi karena siklus. Masuk akal?
Ini hanya aneh karena Anda menandai objek permintaan dengan __block sehingga itu dapat merujuk pada dirinya sendiri. Anda dapat memperbaikinya dengan membuat referensi yang lemah di sampingnya .
sumber
Ini menyebabkan karena mempertahankan diri di blok. Blok akan diakses dari diri sendiri, dan diri disebut dalam blok. ini akan membuat siklus tetap.
Coba selesaikan ini dengan membuat referensi yang lemah
self
sumber
Beberapa kali kompiler xcode memiliki masalah untuk mengidentifikasi siklus retain, jadi jika Anda yakin bahwa Anda tidak mempertahankan completionBlock Anda dapat meletakkan flag kompiler seperti ini:
sumber
Ketika saya mencoba solusi yang disediakan oleh Guillaume, semuanya baik-baik saja dalam mode Debug tetapi macet dalam mode Rilis.
Catatan yang tidak menggunakan __weak tetapi __unsafe_unretained karena target saya adalah iOS 4.3.
Kode saya macet saat setCompletionBlock: dipanggil pada objek "permintaan": permintaan dibatalkan alokasi ...
Jadi, solusi ini berfungsi baik dalam mode Debug dan Rilis:
sumber
apa perbedaan antara referensi __weak dan __block?
sumber
Lihatlah dokumentasi di situs web pengembang Apple: https://developer.apple.com/library/prerelease/ios/#documentation/General/Conceptual/ARCProgrammingGuide/Introduction.html#//apple_ref/doc/uid/TP40011029
Ada bagian tentang mempertahankan siklus di bagian bawah halaman.
sumber