9

Я установил nsurl, который захватывает данные из http. Когда я запускаю инструмент, он говорит, что у меня есть объект NSFNetwork.Неисправность NSURLConnection?

и как мне освободить theConnection in (void) ButtonClicked? или он будет выпущен позже?

- (void)ButtonClicked { 
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:KmlUrl] 
               cachePolicy:NSURLRequestUseProtocolCachePolicy 
              timeoutInterval:20.0f]; 

    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self]; 
    if (theConnection) { 
     // receivedData is declared as a method instance elsewhere 
     NSMutableData *receivedData = [[NSMutableData data] retain]; 
     [self setKMLdata:receivedData]; 
    } else { 
     // inform the user that the download could not be made 
    } 
} 


- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{ 
    // append the new data to the receivedData 
    // receivedData is declared as a method instance elsewhere 
    [KMLdata appendData:data]; 
    NSLog(@"didReceiveData"); 
} 


- (void)connectionDidFinishLoading:(NSURLConnection *)connection 
{ 
    // release the connection, and the data object 
    [connection release]; 
    [KMLdata release]; 
} 


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
{ 
    // release the connection, and the data object 
    [connection release]; 
    // receivedData is declared as a method instance elsewhere 
    [KMLdata release]; 

} 

ответ

2

Это распространенный вопрос и решается магией [автореферат объекта]. В коде это будет выглядеть следующим образом:

NSURLConnection *theConnection = [[[NSURLConnection alloc] initWithRequest:theRequest delegate:self] autorelease]; 

Таким образом, объект не будет автоматически добавлен в «autorelease бассейне» и dealloc'd в начале следующего цикла выполнения после того, как он больше не ссылается.

Надежда, что помогает

Edit: Кроме того, я не понимаю, почему вы нуждаясь называть -retain на переменную receivedData.

+0

Призывая autorelease будет работать, она не будет выполнена в тех случаях, когда делегат выпущенными до подключения освобождается. Лучше всего было бы назначить соединение переменной экземпляра и высвободить + nil, когда это не понадобится. Если соединение ivar по-прежнему назначается, когда объект деаллокируется, перед тем, как освободить соединение, перед тем, как освободить соединение, необходимо установить нуль делегата. – rpetrich

+0

@ rpetrich Я согласен с тем, что ваше предложение более полно, однако было ясно, что его вопрос показал основное непонимание управления памятью на iPhone, и поэтому я хотел дать ему концептуально более легкое решение. – h4xxr

+0

@ rpetrich, можете ли вы привести пример кода. Я пытался решить эту проблему по-разному и все еще испытываю утечку. – Jordan

17

Наконец-то я нашел ответ.

Ошибка в приведенном выше коде (который, кстати, является точным образцом от SDK docs), отсутствует в коде управления памятью. Автореферат - один из вариантов, ручной выпуск - другой. Независимо от того, как вы обрабатываете объект NSURLConnection, вы получаете утечки с помощью NSURLConnection.

Прежде всего, вот решение. Просто скопируйте эти 3 строки кода непосредственно в connectionDidFinishLoading, didFailWithError и в другом месте вы отпустите объект NSURLConnection.

NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0 diskCapacity:0 diskPath:nil]; 
[NSURLCache setSharedURLCache:sharedCache]; 
[sharedCache release]; 

Кредит mpramodjain на http://forums.macrumors.com/showthread.php?t=573253 для кода.

Проблема заключается в том, что SDK кэширует запросы и ответы на iPhone. Даже кажется, что ваша кеш-карта NSMutableURLRequest установлена, чтобы не загружать ответ из кеша.

Глупый факт заключается в том, что по умолчанию он кэширует множество данных. Я передаю много данных (разделенных на несколько подключений) и начал получать предупреждения о памяти, и, наконец, мое приложение скончалось.

Документов нам нужно в NSURLCache (не NSURLConnection), они заявляют:

NSURLCache реализует кэширование ответов на запросы нагрузки URL путем отображения NSURLRequest объектов для объектов NSCachedURLResponse. Это композит встроенной памяти и кэш-память .

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

Эти три строки имеют эффект полного уничтожения кеша. После добавления их в мое приложение (GPS Log) мой подсчет объектов # остается неизменным.

+0

для записи, я переключился на autorelease'd [соединение NSURLConnectionWithRequest: request delegate: self], но я не думаю, что это должно иметь значение. –

+0

Если ваше приложение делает любые другие NSURLRequests, которые _should_ используют кеширование, это решение отключит их. Лучшее решение в этом случае может быть для реализации кэшированные делегата ответа (который имеет тот же эффект): '- (NSCachedURLResponse *) подключение: (NSURLConnection *) подключение willCacheResponse: (NSCachedURLResponse *) cachedResponse { \t возвращение ноль; } ' –

+1

Немного дальше о том, что происходит на самом деле: NSURLCache кэширует ответ на запрос, но использует этот запрос в качестве ключа. Таким образом, он будет придерживаться запроса до тех пор, пока ответы будут кэшироваться. 0-байтовый кеш поражает это, за счет того, что все запросы, сделанные приложением неактивными; реализация метода делегата является более адаптированным подходом. Установка политики кэширования запроса для игнорирования кеша недостаточно. –

5

Привет, вы протестировали этот метод делегата?

- (NSCachedURLResponse *)connection:(NSURLConnection *)connection willCacheResponse:(NSCachedURLResponse *)cachedResponse 
{ 
    return nil; 
} 

Вы можете более точно управлять кешем.

«reset» NSURLCache * sharedCache может вызвать проблемы с другой частью вашего кода?

1

Я использую статический метод/autoreleased подход и, кажется, работает хорошо:

[NSURLConnection connectionWithRequest:theRequest delegate:self]; 

Таким образом, вы даже не придется беспокоиться о выпуске в делегированных обратных вызовов. Оказывается, что счетчик удержания соединения фактически равен 2 (не 1) после того, как он был выделен в приведенных выше примерах, что меняет способ, которым я думал об этой «утечке» памяти.

@rpetrich Я действительно не думаю, что вам нужно беспокоиться о том, что делегат будет выпущен до того, как будет выпущено соединение. Соединение сохраняет его делегат, и само соединение фактически сохраняется в какой-то очереди открытых подключений. Я написал сообщение в блоге моих экспериментов с NSURLConnection на моем блоге:

"Potential leak of object" with NSURLConnection