Neden Objective-C delegelerine genellikle alıkoymak yerine mülk veriliyor?


176

Scott Stevenson tarafından sağlanan harika blogda sörf yapıyorum ve delegelerin 'atama' mülküne karşı 'tutma' atama temel Objective-C kavramını anlamaya çalışıyorum. Her ikisinin de bir çöp toplanmış ortamda aynı olduğunu unutmayın. Çoğunlukla GC tabanlı olmayan bir ortamla (ör: iPhone) ilgileniyorum.

Doğrudan Scott'ın blogundan:

"Assign anahtar sözcüğü, değeri kopyalamak veya tutmak yerine örnek değişkenine doğrudan atayan bir ayarlayıcı oluşturur. Bu, NSInteger ve CGFloat gibi ilkel türler veya temsilciler gibi doğrudan sahip olmadığınız nesneler için en iyisidir."

Delege nesnesine doğrudan sahip olmamanız ne anlama geliyor? Tipik olarak delegelerimi saklıyorum, çünkü onların uçuruma gitmelerini istemiyorsam, saklamak benim için bununla ilgilenecektir. Ben genellikle kendi dataSource uzak UITableViewController soyut ve ayrıca delege. O nesneyi de saklıyorum. UITableView'ımın her zaman temsilci olmasını sağlamak için asla gitmediğinden emin olmak istiyorum.

Birisi ayrıca nerede / neden yanıldığımı daha fazla açıklayabilir mi, bu yüzden Objective-C 2.0 programlamada atama özelliğini alıkoymak yerine delegeler üzerinde kullanmanın bu ortak paradigmasını anlayabilir miyim?

Teşekkürler!


"Temsilciler" ve "iphone" olmadan etiketlendi.
Quinn Taylor

temsilci neden kopya (NSString gibi) yerine
atandı

Yanıtlar:


175

Temsilcileri alıkoymaktan kaçınmanızın nedeni, alıkoyma döngüsünden kaçınmanızdır:

A B'yi yaratır B kendisini delege olarak belirler… A sahibi tarafından serbest bırakılır

B, A'yı elinde tutsaydı, A'nın sahibi olduğu için A serbest bırakılmazdı, bu nedenle A'nın anlaşma kutusu asla çağrılamazdı, bu da hem A hem de B'nin sızmasına neden olur .

A'nın gitmesi konusunda endişelenmemelisiniz, çünkü B'nin sahibi ve böylece ondan kurtuluyor.


Kabul etmiyorum Mike. Ben sadece bir modelin, modunu işten çıkaracak bir delegesi olduğunda bir sorun buldum. Ancak modda bir bellek uyarısı yaptığımda temsilci serbest bırakıyor. Sonra modalımı reddetmeye gittiğimde delege sıfır. Çökme.
Paul Shapiro

Tamam, katılmıyorum, ama bunun bir tasarım hatası olduğu konusunda haklısın. İşten çıkarılma çağrımı gerçek işten çıkarıcı bir çocuk sınıfından geçirdiğimi öğrendim. Bu çocuk sınıfı serbest bırakıldı ve görevden alınmak üzere modelin konteyner temsilcisine geçemedi. Son delege bir işaretçi geçmek için değişti ve bir bellek uyarısı serbest bırakılmadı ve her şey iyi.
Paul Shapiro

2
Kodunuz asla nil delege çökmesine neden olacak şekilde yazılmamalıdır. Yalnızca sahip olan nesnenin sahip olma referansı olmalıdır. Yeniden konumlandırıldığında, sahip olunan nesnelerin delegelerini serbest bırakmadan önce sıfır olarak ayarlamalıdır. Ardından, nil temsilcisine gönderilen iletiler yok sayılır. Bir nil nesne geçme içinde bir mesajın Ancak çökmesine sebep olabilir. Sadece delegelerle bu şekilde ilgilenmediğinizden emin olun.
David Gish

Bekle - bu böyle değil weakmi? Soru neden assignbunun yerine kullanım weak?
wcochran

3
@wcochran: Hayır, bu soru neden assignbunun yerine kullanılıyor retain. Soru ARC'den daha eski; weakve strong(ikincisi ile eşanlamlı retain) ARC tanıtılana kadar mevcut değildi. Hakkında weakvs. assignayrı olarak sormalısınız .
Peter Hosey

44

Çünkü delege iletilerini gönderen nesne delege sahip değil.

Çoğu zaman, başka bir yol budur, çünkü bir denetleyici kendisini bir görünümün veya pencerenin delegesi olarak ayarladığında: denetleyici görünüm / pencereye sahiptir, bu nedenle görünüm / pencere delegesine sahipse, her iki nesnenin de birbirine sahip olması gerekir. Bu, elbette, aynı sonuca sahip bir sızıntıya benzer bir tutma döngüsüdür (ölmesi gereken nesneler hayatta kalır).

Diğer zamanlarda, nesneler akranlardır: muhtemelen ikisi de aynı üçüncü nesneye ait olduğu için biri diğerinin sahibi değildir.

Her iki durumda da, delegeye sahip nesne delegesini korumamalıdır.

(Bu arada en az bir istisna var. Ne olduğunu hatırlamıyorum ve bunun için iyi bir neden olduğunu düşünmüyorum.)


ek (2012-05-19 eklendi): ARC altında, weakyerine kullanmalısınız assign. Zayıf başvurular nilnesne öldüğünde otomatik olarak ayarlanır ve temsilci nesnenin ölü temsilciye ileti gönderme olasılığını ortadan kaldırır.

Herhangi bir nedenden ötürü ARC'den uzak duruyorsanız , en azından assignnesnelere işaret eden özellikleri değiştirin unsafe_unretained; bu, bunun bir nesneye erişilemeyen ancak sıfır olmayan bir referans olduğunu açıkça ortaya koyar.

assign hem ARC hem de MRC altındaki nesne dışı değerler için uygun kalır.


13
NSURLConnectiondelegesini korur.

Evet, kullanın weak, ancak bu orijinal soruyu cevaplamıyor: Apple neden assignbunun yerine kullanıyor weak?
wcochran

@wcochran: Asıl soru “ korumakassign yerine delege özellikleri neden verilmiştir ”; sorulduğunda yoktu. Sorunuz, ayrı olarak sormanız gereken farklı bir sorudur. Cevaplamaktan mutluluk duyarım. weak
Peter Hosey

@wcochran ve Peter, bu soru başka bir yerde mi soruldu?
Bay Rogers

17

Atanmış bir temsilciniz olduğunda, nesne yeniden dağıtıldığında o delege değerinin her zaman sıfır olarak ayarlanmasının çok önemli olduğunu unutmayın. başka yerde yaptım.


“Atanmış bir temsilciniz olduğunda, nesne yeniden yerleştirilecek olduğunda bu delege değerinin her zaman sıfır olarak ayarlanmasının çok önemli olduğunu unutmayın” Neden?
Peter Hosey

2
Herhangi bir başvuru ayarlanmadan bırakıldığı için, bir nesne dağıtıldıktan sonra geçersiz olacaktır (belleğe artık beklenen nesne türüne ayrılmamış olarak işaret ederek) - ve bunu kullanmaya çalıştığınızda çökmeye neden olur. Hata ayıklayıcıda bunun bir işareti, hata ayıklayıcının bazı değişkenin, aslında değişken olarak bildirildiğinden tamamen yanlış görünen bir tür olduğunu iddia etmesi.
Kendall Helmstetter Gelner

1
Bu, yalnızca temsilci olduğunuz nesne bir zamanlayıcı veya eşzamansız geri arama gibi başka bir kaynak tarafından tutuluyorsa gereklidir. Aksi takdirde, serbest bırakıldıktan sonra dağıtılacak ve temsilci yöntemlerini çağırmaya çalışmaz.
Andrew Pouliot

@Andrew: Bu doğru, ama her zaman delegeleri iptal etmek için bir uygulama yaparsanız, o zaman ne zaman önemli olduğunu unutmazsınız veya yanlışlıkla tutulan bir nesneyi aşırı tutarsanız ve yine de kalır. Temsilci seçerseniz, sonuç bir sızıntı ve ardından bir çökme yerine sadece bir sızıntıdır.
Kendall Helmstetter Gelner

1

Bunun arkasındaki nedenlerden biri, koruma döngülerinden kaçınmaktır. A ve B'nin her iki nesnenin birbirine referans verdiği ve hiçbirinin bellekten serbest bırakılmadığı senaryodan kaçınmak için.

Acutally atamak , NSInteger ve CGFloat gibi ilkel türler veya delegeler gibi doğrudan sahip olmadığınız nesneler için en iyisidir.


Bu, sırasıyla OP'nin teklifinden ve kabul edilen cevaptan kopyalandı, değil mi?
dakab
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.