Сохраняет ли NSURLConnection свой делегат?
Резюме моего вопроса: сохраняет ли NSURLConnection свой делегат?
Подробный вопрос и сценарий:
У меня есть пользовательский класс, называемый JsonDownloader, который принимает URL-адрес и возвращает NSDictionary JSON, который возвращает URL-адрес.
В приложении для iPhone я делаю что-то вроде этого. (метод init запускает весь процесс)
- (void)viewDidLoad {
JsonDownloder *temp = [[[JsonDownloader alloc] initWithURL:urlString returnDataTo:self]];
[temp release];
[super viewDidLoad];
}
Когда JsonDownloader завершает загрузку и разбор, он выполняет обратный вызов объекта returnDataTo: в данном случае вызывающего объекта.
Это работает отлично. Даже если я введу 30-секундную задержку в ответе на мои веб-серверы, JsonDownloader все еще существует и правильно выполняет обратный вызов.
Итак, мои вопросы таковы: что удерживает JsonDownloader до конца цикла событий? Я прямо его освобождаю.
Моя догадка заключается в том, что NSURLConnection должен делать удержание на своем делете, но я ничего не видел в документации. У кого-нибудь есть идеи?
Ответы
Ответ 1
Существует не так много сеттеров, которые не копируют и не сохраняют переданную ему переменную, чтобы память указанной переменной не перераспределялась на что-то еще, когда ее счетчик сохранения достигает нуля.
Однако ответ ДА, он делает. Немного тестового кода показывает, что количество удерживаемых делегатов увеличивается:
NSLog(@"Retain count before: %d", [self retainCount]);
NSURLRequest* request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://google.com"]];
NSURLConnection* conn = [NSURLConnection connectionWithRequest:request delegate:self];
NSLog(@"Retain count after: %d", [self retainCount]);
который создается в журнале:
Running…
2009-07-09 02:13:40.516 delegateRetain[45123:a0f] Retain count before: 1
2009-07-09 02:13:40.525 delegateRetain[45123:a0f] Retain count after: 2
Debugger stopped.
Итак, вы можете видеть довольно ясно, что в connectionWithRequest:delegate:
"я" действительно имеет увеличенный счетчик +1. Если вы чувствуете себя храбрым и хотите общаться с богами EXC_BAD_ACCESS, добавьте
[conn dealloc];
NSLog(@"Retain count after dealloc: %d", [self retainCount]);
который снова распечатает "1", показывая декремент postalloc. Однако вы получите хороший Program received signal: "EXC_BAD_ACCESS".
, потому что NSAutoreleasePool
попытается освободить соединение, и он исчезнет;)
Ответ 2
Большинство свойств делегата не сохраняются, а назначаются для предотвращения циклических ссылок. См. этот вопрос об этом.
Однако NSUrlConnection не имеет определенного свойства делегата. Вы должны указать делегата вместе с инициализацией соединения. Я думаю, именно поэтому он получает удержание, как показал Дэйв Марторана.
Ответ 3
Да, "Соединение сохраняет делегат. Он освобождает делегат, когда соединение заканчивает загрузку, завершает работу или отменяется" в соответствии с Xcode Documentation для -[NSURLConnection initWithRequest:delegate:]
по специальным соображениям. См. Также: Неисправность утечки памяти NSURLConnection