Когда вызывать релиз по NSURLConnection делегату? - PullRequest
5 голосов
/ 27 октября 2009

При передаче делегата объекту NSUrlConnection примерно так:

[[NSURLConnection alloc] initWithRequest:request delegate:handler];

когда вы должны вызвать release для делегата? Должно ли оно быть в connectionDidFinishLoading? Если так, я продолжаю получать exec_bad_access. Я вижу, что мои делегаты протекают через инструменты.

Спасибо

Ответы [ 5 ]

6 голосов
/ 07 мая 2011

Взято из моего сообщения в блоге здесь: http://i.ndigo.com.br/2012/01/releasing-nsurlconnection-and-its-delegate/


Вам нужно будет уделить дополнительное внимание объекту делегата, поскольку для NSURLConnection существует особое внимание для делегата: он всегда сохраняется.

http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html#//apple_ref/doc/uid/20001697-BAJDDIDG

initWithRequest: делегат :

Особые замечания : Соединение сохраняет делегировать. Это освобождает делегата, когда соединение завершает загрузку, не выполняется или отменяется.

Итак, учитывая это, у вас есть несколько вариантов, чтобы ваш делегат был выпущен правильно, и я попытаюсь объяснить 2 простых.

Первый и наиболее часто используемый - это использование того же класса, который инициализирует NSURLConnection, что и делегат.

[[NSURLConnection alloc] initWithRequest:request self];

Таким образом, ваш класс хранения будет увеличен на 1 при запуске подключения, а затем уменьшен на 1 после завершения загрузки, сбоя или отмены подключения, что не приведет к утечкам памяти.

Второй вариант, который вы пытаетесь сделать, - это использовать другой объект для обработки всех вызовов соединения. Это также хорошо работает, но вам потребуется дополнительное внимание с памятью. Одна простая вещь, которую вы можете сделать, чтобы решить свою проблему, - это инициализировать соединение с помощью объекта автоматического выпуска.

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];

//creates the connection with handler as an autorelease object
[[NSURLConnection alloc] initWithRequest:request delegate:[handler autorelease]];

ИЛИ вы можете освободить ваш обработчик сразу после создания соединения (так как оно уже будет сохранено соединением)

//creates the handler object
MyHandlerClass *handler = [[MyHandlerClass alloc] init];

//creates the connection with handler
[[NSURLConnection alloc] initWithRequest:request delegate:handler];

//releases handler object
[handler release];

В обоих случаях владение объектом-обработчиком остается только с классом соединения, который освобождает объект-обработчик сразу после завершения загрузки, сбоя или отмены, что снова не приводит к утечкам памяти.

РЕДАКТИРОВАТЬ: выполнив любой из вышеперечисленных вариантов, вам не нужно беспокоиться об освобождении делегата (но вы все равно должны освободить соединение) в методах connection:DidFinishLoading и connection:didFailWithError.

3 голосов
/ 27 октября 2009

Это будет зависеть от того, что за объект handler и как вы его используете. Например, я обычно использую self в качестве моего делегата:

[[NSURLConnection alloc] initWithRequest:request delegate:self];

Мне не нужно вызывать release для self, поскольку делегаты не сохраняются и self будет освобожден другим объектом.

Если handler - новый объект, вам придется его освободить (и connectionDidFinishLoading: должно быть в порядке, если вам не нужно использовать объект handler для чего-то другого).

Вы знакомы с правилами управления памятью в Какао ?

Можете ли вы дать лучшее представление о том, что такое handler и как вы его используете?

0 голосов
/ 08 августа 2014

NSURLConnection делегат сохраняется.

Используйте код в ViewDidLoad в среде без ARC.

NSLog(@"Retain count %d",[self retainCount]);
NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:nil delegate:self];
NSLog(@"Retain count %d",[self retainCount]);
0 голосов
/ 28 октября 2009

обработчик объекта используется для реализации connectionDidFinishLoading didReceiveData и т. Д. Я часто обращаюсь к нескольким веб-службам, и вместо создания одного объекта для каждого у меня есть центральный класс для всего этого:

@interface DataService : NSObject {} 

- (void) search:(NSString *) name byAddress:(NSString *)address; 

@end 

поэтому реализация этого метода создает делегат для передачи:

SearchDelegate *delegate = [[SearchDelegate alloc] init]; 
[self sendRequestToUrl:urlString withJson:jsonString andHandler:delegate];

что я вижу в Инструментах, так это то, что в SearchDelegate есть утечка памяти ... поэтому я думаю, что на самом деле она сохраняется.

Немного повозившись, я изменил свой метод sendRequestToUrlMethod, чтобы он имел:

// http code setup blah...

[[NSURLConnection alloc] initWithRequest:request delegate:handler];
[handler release];

и, похоже, это вызвало утечку памяти, сообщаемую в приборах.

0 голосов
/ 27 октября 2009

Вам необходимо освободить соединение, а не делегат. Я думаю, что класс NSURLConnection не сохраняет делегата, поэтому вы получаете сбой при попытке его освободить.

Два места для освобождения соединения: соединение: DidFinishLoading и соединение: didFailWithError.

...