KVO ve ARC nasıl kaldırılır


87

ARC altındaki bir nesneden bir gözlemciyi nasıl kaldırırsınız ? Gözlemciyi ekleyip kaldırmayı unutur muyuz? Belleği artık manuel olarak yönetmiyorsak, nerede gözlem yapmaktan vazgeçeriz?

Örneğin, bir görünüm denetleyicisinde:

[self.view addObserver:self
            forKeyPath:@"self.frame"
               options:NSKeyValueObservingOptionNew 
               context:nil];

Önceden, removeObserver:görünüm denetleyicisinin deallocyöntemini çağırırdım.


4
KVO .frame için çok kötü bir fikir olduğunu unutmayın. Apple mühendisleri tarafından StackOverflow'da başka bir yerde yazılacağı gibi, UIKit'in çerçeve özelliği KVO uyumlu değildir. İşe yaradığında, sadece şans eseri.
steipete

2
KeyPath'iniz @"frame"yerine olması gerekmez @"self.frame"mi?
Besi

Yanıtlar:


126

Yine de -dealloc, anahtar değerlerin gözlemini kaldırmak için uygun yer gibi görünen ARC altında uygulayabilirsiniz . Artık [super dealloc]bu yöntemden arama yapmıyorsunuz .

Daha -releaseönce geçersiz kıldıysan , işleri yanlış yapıyorsun.


1
Bundan emin misin? Clang.llvm.org/docs/… , bölüm 7.1.2'den alıntı yapıyorum . dealloc: "Gerekçe: ARC örnek değişkenlerini otomatik olarak yok etse de, bir dealloc yöntemi yazmak için hala geçerli nedenler vardır, örneğin tutulamayan kaynakları serbest bırakmak. Böyle bir yöntemde [super dealloc] 'u çağırmamak neredeyse her zaman bir hatadır."
Elise van Looij

@ElisevanLooij Evet bu doğru. Bu dersten türüyorsanız, aramanız gerektiği açık görünüyor [super dealloc]. Bunu sizin için başka kim yapmalı?
Björn Landmesser

@ElisevanLooij Oops, daha önce kontrol etmeliydim. [super dealloc]Dealloc yönteminde çağrı yapılmasına izin verilmez . Bahsedilen sınıfı alt sınıflara ayırırken bunun nasıl çalışacağı hakkında hiçbir fikrim yok. Belki de bunun finalizeyerine kullanılması tavsiye edilir (aradığınız yerde [super finalize])
Björn Landmesser

17
@ElisevanLooij - Oraya değinmeye çalıştıkları nokta, manuel bellek yönetimi durumuyla ilgili. Bu [super dealloc]yöntemde sonuncuyu çağırmamak hemen hemen her zaman manuel bellek yönetiminde bir hata olduğundan, derleyici onu şimdi sizin için halleder, bu yüzden -deallocartık doğrudan arayamazsınız. -deallocARC altında bir yönteme koyduğunuz tek şey , serbest bırakmanız gereken nesne olmayan kaynaklar veya gözlemcileri kaldırmak gibi temizleme görevleridir. Kullandıkları üslup biraz muğlak ama kastettikleri bu.
Brad Larson

7
@ BjörnMilcke - Elise'in cevabına yorum yaptığım gibi, -finalizebunun için -deallocasla çağrılmayan çöp toplama altında kullanılıyor , ancak bu kodu -deallocARC altına yerleştirmek tamamen kabul edilebilir . [super dealloc]sizin için otomatik olarak çağrılır, bu yüzden ARC altında çağırmak bir hatadır.
Brad Larson

1

Bunu bu kodla yapıyorum

- (void)dealloc
{
@try{
    [self.uAvatarImage removeObserver:self forKeyPath:@"image" context:nil];
} @catch(id anException) {
    //do nothing, obviously it wasn't attached because an exception was thrown
}
}    

2
İstisna işlemenin amacı nedir dealloc? Bununla ilgili bir şey yapmak için çok geç.
Abizern

Dealloc'ta bir örnek değişkenindeki gözlemcileri kaldırmanın anlamı nedir? Bu uAvatarImage, ana yollarına abone olduğu gözlemcilerle birlikte yakında kaldırılacaktır.
shoumikhin

1
@shoumikhin ARC kullanıyorum ve dealloc yönteminde gözlemciyi kaldırmak zorunda kaldım. Bende de seninle aynı soru var. Ancak, sınıfın birden çok örneğini çalıştırdığımda, sonunda exc_bad_address hatası aldım. Bunu yapmak sorunu çözdü. Ayrıca, stackoverflow.com/questions/32490808/… buradaki yanıt , sorunu keşfetmeme yardımcı oldu.
mac10688

-2

Yığın taşması konusunda başka bir yerde , Chris Hanson bu amaç için sonlandırma yöntemini kullanmayı ve sahiplerin nesnelere bittiğini söyleyebilmesi için ayrı bir geçersiz kılma yönteminin uygulanmasını tavsiye ediyor. Geçmişte Hanson'un çözümlerini iyi düşünülmüş buldum, bu yüzden onunla devam edeceğim.


13
ARC'den değil, oradaki çöp toplamadan bahsettiğine dikkat edin (cevabı 2008'de yazılmıştır). Çöp toplama altında -deallocasla aranmaz. ARC'de öyle. -deallocChris Lattner'ın (ne hakkında konuştuğunu bilen) Apple'ın geliştirici forumlarında belirttiği gibi, KVO gözlemcilerini kaldırmak tamamen kabul edilebilir : devforums.apple.com/message/475850
Brad Larson

3
Tüm bu işi yaptığınız için teşekkürler Brad. Sonlandırmak için hayır, ayrıştırmaya evet ama [süper dealloc] olmadan. Gerçekten basit, bir kez öğrendikten sonra. Hey, @drunknbass, o adamın cevabını kabul et!
Elise van Looij
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.