ASIHTTPRequest, EXC_BAD_ACCESS, когда запрос завершен

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

-(void)doDownload{
    NSURL *url = [NSURL URLWithString:@"http://www.someurl.com/?"];
    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
    [request setPostValue:@"someValue" forKey:@"someField"];
    [request setRequestMethod:@"POST"];

    [request setDelegate:self];
    [request setDidFinishSelector:@selector(requestFinished)];
    [request startAsynchronous];
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    // Use when fetching text data
    NSString *responseString = [request responseString];

}

requestFinished никогда не вызывается. Я получаю исключение в ASIHTTPRequest.m, -handleStreamCompleted:

if (fileError) {
    [self failWithError:fileError];
} else {
    [self requestFinished];   <----- this call fails
}

Любые подсказки?


person Vegar    schedule 29.01.2010    source источник


Ответы (3)


Вы уверены, что ваш класс, реализующий - (void)requestFinished:(ASIHTTPRequest *)request, все еще существует, когда запрос завершится? Мне кажется, что класс освобождается слишком рано. Обратите внимание, что свойство delegate не сохраняет свое содержимое.

Вы можете добавить [self retain] к doDownload и [self release] к - (void)requestFinished:(ASIHTTPRequest *)request, но убедитесь (!), что [self release] не вызывается слишком часто. Это также возможная утечка памяти, если запрос никогда не завершится. Было бы лучше сохранить ваш класс в другом месте.

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

person MrMage    schedule 29.01.2010
comment
Кажется, это правильный ответ. У меня есть жизненная проблема управления, которую нужно решить. Теперь я создаю класс загрузки, вызываю метод и сразу же выпускаю его. Я должен внедрить некоторую систему обратного вызова, чтобы владелец экземпляра загрузки знал, когда что-то сделано. В конечном итоге мне это понадобится, чтобы скрыть просмотры прогресса, обновить данные и т. д. Спасибо. - person Vegar; 30.01.2010
comment
Как это можно сделать при работе с ARC? См. мою тему здесь. - person dhrm; 02.12.2011
comment
Тош. @tomute прав, имя селектора requestFinished:, а не requestFinished, вот и вся проблема. Не нужно ломать голову над жизненными циклами, удержанием и прочим. - person Elise van Looij; 29.12.2011

Следующая строка вашего кода кажется неправильной.

[request setDidFinishSelector:@selector(requestFinished)];

Метод requestFinished имеет аргумент (ASIHTTPRequest *).
Поэтому вам следует добавить ":", когда вы устанавливаете селектор следующим образом.

[request setDidFinishSelector:@selector(requestFinished:)];
person tomute    schedule 29.01.2010
comment
Поверю вам на слово ;-) Спасибо. - person Vegar; 30.01.2010

[строка ответа на запрос];

Перед этим вызовом проверяйте keepCount запроса. Вероятно, он равен нулю :) Если да - не забудьте сохранить его при создании в методе doDownload.

person alexandrmoroz    schedule 29.01.2010
comment
Я не могу проверить запросы keepCount в requestFinished, так как requestFinished никогда не вызывается. - person Vegar; 29.01.2010