2011-12-13 32 views
6

Bir arkadaşım NSDictionary ile bazı garip davranışlar keşfetti ve neden olduğunu merak ediyorum. Aşağıdaki kodu düşünün:Bu Objective C çağrısı neden asılı görünüyor?

NSDictionary *dict = [[NSDictionary alloc] init]; 

// Oops, we can't mutate an NSDictionary 
[dict setObject:[[NSNull alloc] init] forKey:@"test"]; 
NSLog(@"Set"); 

kodu " 'NSDictionary' ': forKey: setObject' yanıt veremeyebilir" diye derleme üzerine bir uyarı üretir. Yani iyi ve güzel, hepsi ve yine de çalıştırırsanız, konsolda bu çıktıyı alırsınız:

- [__ NSCFDictionary setObject: forKey:]: yöntem değişmez nesneye gönderilen mutasyona

Yine, tam olarak ne olmasını beklerdiniz. Bununla birlikte, bu noktada uygulama , yakalanmamış bir istisna nedeniyle kilitlenmez veya sonlanmaz. SetObject: forKey: yöntemi hiçbir zaman geri dönmez ve uygulama askıda kalır; Aşağıdaki NSLog asla yürütülmez. GDB'yi kullanarak yönteme geçmeyi denerseniz, hata ayıklama sona erer, ancak herhangi bir açık hata mesajı olmadan görünür. Uygulama çalışmaya devam eder, ancak hata ayıklayıcı kodda kodun neresinde "sıkışmış" olduğuna dair hiçbir ipucu vermez.

Neler oluyor burda? Uygulama aslında bu durumda ne yapıyor ve neden bir NSInternalInconsistencyException veya benzeri bir şeyle çakışma yapmıyor?

Edit: Sormuş olanlar için, "Apple LLVM derleyici 2.1" ile bina OS X Lion (10.7.2) üzerinde XCode 4.1 çalıştırıyorum. XCode 4'te yeni bir Kakao projesi ile aldığınız tüm varsayılan ayarları kullanıyorum. Programda hata ayıklamadan veya "Çalıştır" dan bağımsız olarak aynı çökmeyen davranışı yaşıyorum. Hata ayıklama yapısından Sürüm binasına geçişte fark yoktur. .app dosyasını Finder'da elle bulabilir ve XCode'un dışında yürütmek için çift tıklayabilir ve hala çökmez.

+1

Hata ayıklayıcının altında çalıştırmayı deneyin; Bahse girerim zor çöküşler. Hata ayıklayıcı ortamının, çalışma ortamı ortamında özellikle istisnalar etrafında bazı beklenmedik etkilere sahip olabileceğini ve bunları vurduğunuzda ne olacağını görebilirsiniz. –

+2

İstisna atıldığında, istisnayı yakalayan her ne olursa olsun, kontrol devam eder, istisnadan sonraki * değil * sonraki satır. Örneğinizde ya hata ayıklayıcı ya da çalışma zamanının bağırsakları istisna "yakalandı". Her durumda, NSLog'un -setObject'ten sonra gerçekleşmesini beklemezsiniz: forKey: bir istisna attı. –

+0

@VincentGable: Kabul edildiğinde, program çökerse NSLog'un çağrılmadığı en ufak bir sürpriz olmayacaktı. Beni şaşırtan şey, ne çökerse ne de bir sonraki satıra doğru ilerlemektir. Biri ya da diğeri yapması gerektiği gibi görünüyor. Ben sordum olanlar için, ben çalıştığım ortam hakkında bazı ek ayrıntılar ile soruyu güncelledik. –

cevap

1

İstisnalar, AppKit programlarını kilitlemez. NSApplication, kodunuzun yapmadığı istisnaları yakalayan bir varsayılan istisna işleyicisi yükler. Sonra normal olarak runloop'a geri dönün.

Birçok uygulama bu davranışı sergilemektedir. Açıklanamayan boş görünümlerin/pencerelerin yaygın bir nedeni. Bir görünüm, çizimi bitirmeyi başarmadan önce bir istisna olursa, görünüm boş olacak, ancak uygulama çökmeyecek. İstisnalar, varsayılan istisna eylemcisini kasıtlı olarak kilitlemek için değiştirdiğinizde yalnızca bir çökmeye neden olur.

+0

bir çoğunu Teşekkürler, bu çoğunlukla benim cevaplar soru. Yine de kafam karıştıran bir şey var, ancak istisnasın yakalanmasından sonra uygulamanın ana olay döngüsüne geri döndüğünü göremiyorum. Yoksa bu farklı bir iş parçacığında mı gerçekleşir? AppKit'in iç işleyişine aşina değilim. –