2012-08-06 17 views
5

In this question, aşağıdaki kodu hakkında sorular ve döngüleri korumak:bloklarda Zayıf referanslar ve muhafaza döngüleri

__weak Cell *weakSelf = self; 
NSBlockOperation *op = [NSBlockOperation blockOperationWithBlock:^{ 
     UIImage *image = /* render some image */ 
     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
      [weakSelf setImageViewImage:image]; 
     }]; 
    }]; 
    [self.renderQueue addOperation:op]; 

tüm cevaplar bu kodun bir yol açmaz çünkü burada zayıf referans kullanılarak, gerekli değildi devlet döngüsü koru. Ancak, bazı daha kodla deneme sırasında, şu bir muhafaza döngüsüne yol vermez (Ben zayıf bir başvuru kullanmak istemiyorsanız, geçerli görünüm kontrolörü ayırmanın değil)

//__weak ViewController *weakSelf = self; 
    MBItem *close = [[MBItem alloc] initWithBlock:^{ 
     [self dismissModalWithDefaultAnimation:NO]; 
    }]; 
    NSMutableArray *items = [[NSMutableArray alloc] initWithObjects:close, nil]; 
    [self.childObject setItems:items]; 

Neden mü ikincisi sonuç içinde Bir muhafaza döngüsü, ancak ilk değil mi?

+2

Anahtar sözcük "CYCLE tut" şeklindedir. Bende seni koruyorum ve sen beni korusun, kim önce girsin? –

cevap

12

Eski kod __weak kullanmak istemiyorsanız bu döngüyü tutmak oluşturur:

  • (NSBlockOperation *)op dış bloğunu korur
  • dış blok korur self (eğer __weak kullanmıyorsanız)
  • self(NSOperationQueue *)renderQueue
  • (NSOperationQueue *)renderQueue korur (NSBlockOperation *)op
  • korur

Bu döngüdeki nesnelerin hiçbiri, bu bağlantılardan biri bozulmadığı sürece ayrılabilir. Ancak bize gösterdiğiniz kod, tutma döngüsünü kırıyor. op yürütmeyi bitirdiğinde, renderQueue onu serbest bırakarak, tutma döngüsünü bozar.

  • (MBItem *)close
  • blok korur
  • self
  • selfchildObject
  • childObject(NSMutableArray *)items
  • (NSMutableArray *)items(MBItem *)close korur korur korur bloğu korur:

    Ben yeni kod, bu döngüyü muhafaza oluşturur şüpheli

Bu bağlantılardan birini kırmayacak bir şey olmazsa, döngüdeki nesnelerin hiçbiri ayrılmamış olabilir. Koruma döngüsünü bozan herhangi bir kod göstermediniz. Açıkça bozan bir olay yoksa (örneğin childObject.items'u temizleyerek), tutma döngüsünü kırmak için __weak'u kullanmanız gerekir.

8

Size ikinci örneğinizde tutma döngüsünün nedenini anlatamam, çünkü MBItem'u bilmiyorum, ancak bloklarla iki farklı kullanım deseni vardır. self ayırmanın değil böylece bloktur önce

[startSomeOperationWithCompletionBlock:^{ 
    [self doSomeThing]; 
}]; 

blok self bir başvuru korur:

Eğer blok ardından sadece blokta self kullanabilirsiniz her durumda yürütmek bekliyorsanız idam. Ancak blok yürütüldükten sonra, bu referans (ve tutma döngüsü) gitti.

muhtemelen self blok, yürüttü veya eğer mümkünse blok hiç denilen olmayacak önce serbest bırakıldığını istiyorsanız

, o zaman zayıf bir başvuru kullanmanız ve iç değerini kontrol etmek zorunda blok: self ayırmanın böylece blok, bu durumda self korumaz

__weak MyClass *weakSelf = self; 
[startSomeOperationWithCompletionBlock:^{ 
    MyClass *strongSelf = weakSelf; 
    if (strongSelf) { 
     [strongSelf doSomeThing]; 
    } 
}]; 

. Bu durumda, weakSelf otomatik olarak nil olarak ayarlanır. Bu nedenle, blok son olarak çalıştırılırsa, weakSelf'un hala geçerli olup olmadığını kontrol etmeniz gerekir. bloğun içine güçlü bir referans strongSelf atama

(ya da sadece nil mesaj göndermek no-op, çünkü., kullanabilirsiniz) blok yürütülürken ayırmanın gelen self engeller.

+0

Eğer blok yürütülürse, ancak yine de bazı dizide tutuluyorsa, tekrar kullanılabilir mi? Sanırım, dizi temizlenene kadar kendiliğinden ayrılmayacak mıyım? – Snowman

+0

Evet, bence bu, @robmayoff'un cevabında açıkladığı şeydir. –

+0

Blok içindeki zayıf (veya benim durumumunsafe_unretained) işaretçisine güçlü bir başvuru oluşturmak, benzer bir sorunu çözmüştü ve sınıfın blok yürütmesinin ayrıldığı yerdeydi. Teşekkürler! – SRandazzo