2013-04-17 27 views
10

Böyle bir bloğunun içinde küresel bir değişken ya da özelliğini kullanmak zorunda her zaman "bu blokta kuvvetle yakalayan kendini bir tutmak döngüye yol açması muhtemeldir" böyle hatta BOOL değişkenleri hakkında şikayetmesajı

BOOL *iis = isItSaving; 
id myself = self; 

self.save = ^(){ 
    if (iis == NO) { 
     [myself saveMyFile]; 
    } 
}; 

veya Xcode bir muhafaza döngüye yol açma ihtimali olan bu blokta kuvvetle kendini yakalayan" şikayet edecek ...?

Her şey bir bloktan önce tekrar ele alındığında topal bir çözüm olarak görünüyor.

Bu doğru yolu mu? Zarif bir yolu var mı?

Bu şeyler çirkin. ARC kullanıyorum.

cevap

20

Sorun, yalnızca self numaralı başvuruya açık veya dolaylı olarak engellendiğinde ortaya çıkar. Global değişkenlere erişirken yayınlanan bir uyarı yok. Sizin durumunuzda muhtemelen bir (boole) ivar'a erişmişsinizdir. Ivar'a erişim, self'u dolaylı olarak kullanır, bu yüzden derleyici, bir tutma döngüsü hakkında sizi uyarır (doğru).

korumak döngüsünü düzeltmek için yaygın yolu şudur:

typeof(self) __weak weakSelf = self; 

self.save = ^() { 
    typeof(weakSelf) __strong strongSelf = weakSelf; 
    if (strongSelf != nil && ! strongSelf->isItSaving) { 
     [strongSelf saveMyFile]; 
    } 
}; 

... ve, evet, o blokların çirkin kısmının biraz. sizin örnekte

+1

adam, bu cehennem kadar çirkin. Her şeyi yeniden ilan etmek zorunda ... teşekkürler. – SpaceDog

+0

@MarkAmery Evet, clang daha fazla sorun yakalar. Ve doğru, kapalı nesnenin ömrü en azından blok bitene kadar uzatılmalıdır. Düzenleme ... –

+1

@NikolaiRuhe * "kapama nesnesinin ömrü en azından blok tamamlanana kadar uzatılmalıdır" * - güzel, ilk önce bloğun içinde 'self''e güçlü bir başvuru oluşturmanın herhangi bir nedenini fark etmedim __unsafe_unretained' işlevinin kullanılması tercih edilebilir, ancak bu ifade tek başına onu inanılmaz derecede netleştirir. İsterseniz, cevabınızdaki iki yaklaşımı bile karşılaştırabilirsin. –

4

Kullanım NikolaiRuhe yanıtına @ ek olarak __unsafe_unretained typeof(self) weakSelf = self;

+0

Sanırım ARC ile __unsafe_unretained kullanamazsınız – SpaceDog

0

, özelliklerini

BOOL *iis = isItSaving; 
id myself = self; 

ilan strong başvuruları ima, böylece muhafaza döngüsünü engellemek için __weak kendini kullanın. O zaman neden blok içinde zayıf benlik için bir __strong referans bildirmeniz gerektiğini merak edebilirsiniz ve bu blokun ömrü boyunca serbest bırakılmamasını sağlamak için, serbest bırakılırsa aksi takdirde weakSelf->isItSaving kopar.