Мой друг обнаружил какое-то странное поведение с NSDictionary, и мне любопытно, почему это происходит. Рассмотрим следующий код:
NSDictionary *dict = [[NSDictionary alloc] init];
// Oops, we can't mutate an NSDictionary
[dict setObject:[[NSNull alloc] init] forKey:@"test"];
NSLog(@"Set");
При компиляции код выдает предупреждение о том, что «NSDictionary может не отвечать на setObject: forKey:». Это все хорошо, и если вы все равно запустите его, вы получите этот вывод в консоли:
-[__NSCFDictionary setObject:forKey:]: мутирующий метод отправляется в неизменяемый объект
Опять же, именно то, что вы ожидаете. Однако в этот момент приложение не аварийно завершает работу из-за неперехваченного исключения. Метод setObject:forKey: просто никогда не возвращается, и приложение зависает; следующий NSLog
никогда не выполняется. Если вы попытаетесь перейти или войти в метод с помощью GDB, отладка просто закончится, но без какого-либо явного сообщения об ошибке. Приложение продолжает работать, но отладчик не дает сведений о том, где в коде выполнение «застряло».
Что тут происходит? Что на самом деле делает приложение в этом случае и почему оно не падает с NSInternalInconsistencyException или чем-то подобным?
Редактировать: для тех, кто спрашивал, я запускаю XCode 4.1 на OS X Lion (10.7.2) с помощью «компилятора Apple LLVM 2.1». Я использую все настройки по умолчанию, которые вы получаете с новым проектом Cocoa в XCode 4. Я испытываю одно и то же поведение без сбоев независимо от того, отлаживаю ли я программу или просто «запускаю» ее. Переход от сборки Debug к сборке Release не имеет значения. Я даже могу найти файл .app вручную в Finder и дважды щелкнуть по нему, чтобы выполнить его вне XCode, и он все равно не падает.