Асинхронные броски NSURLConnection - PullRequest
6 голосов
/ 10 мая 2010

Я не совсем уверен, почему мой код выдает EXC_BAD_ACCESS, я следовал инструкциям в документации Apple:

-(void)getMessages:(NSString*)stream{

    NSString* myURL = [NSString stringWithFormat:@"http://www.someurl.com"];

    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:myURL]];

    NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
    if (theConnection) {
        receivedData = [[NSMutableData data] retain];
    } else {
        NSLog(@"Connection Failed!");
    }

}

И методы моего делегата

#pragma mark NSURLConnection Delegate Methods
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    // This method is called when the server has determined that it
    // has enough information to create the NSURLResponse.

    // It can be called multiple times, for example in the case of a
    // redirect, so each time we reset the data.

    // receivedData is an instance variable declared elsewhere.
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // Append the new data to receivedData.
    // receivedData is an instance variable declared elsewhere.
    [receivedData appendData:data];
}

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

    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    // release the connection, and the data object
    [connection release];
    [receivedData release];
}

Я получаю EXC_BAD_ACCESS для didReceiveData. Даже если этот метод просто содержит NSLog, я получаю ошибку.

Примечание: полученныйData является NSMutableData * в моем заголовочном файле

Ответы [ 7 ]

6 голосов
/ 10 мая 2010

Используйте NSZombieEnabled точку останова и проверьте, какой объект освобожден.

Также проверьте:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if ([response expectedContentLength] < 0)
    {
        NSLog(@"Connection error");
            //here cancel your connection.
            [connection cancel];
        return;
    }
}
5 голосов
/ 10 мая 2010

Я следовал инструкциям в документации Apple:

Это не правда. В обоих случаях вы нарушаете правила:

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

    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSErrorFailingURLStringKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // do something with the data
    // receivedData is declared as a method instance elsewhere
    NSLog(@"Succeeded! Received %d bytes of data",[receivedData length]);

    // release the connection, and the data object
    [connection release];
    [receivedData release];
}

В обоих случаях вы не получаете объект connection с alloc, метод, начинающийся с new или содержащий copy. Вы не владеете connection в этих методах. Вы не должны выпускать это в этих методах.

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

[receivedData release];
receivedData = nil;

Таким образом, случайно не выйдет больше, чем один раз.

2 голосов
/ 07 марта 2011

Я получил ту же ошибку при отладке с устройством, хотя в симуляции не было никаких проблем. Добавление следующей строки кода после освобождения receiveData решило проблему:

receivedData = nil;
2 голосов
/ 10 мая 2010

Если вы получаете сообщение об ошибке didRecieveData независимо от кода внутри, похоже, ваш делегат освобожден?

Я бы проверил, что объект, содержащий метод getMessages, не освобождается (или автоматически освобождается), пока соединение не завершило получение данных.


РЕДАКТИРОВАТЬ: комментарии ниже показывают, что мой ответ выше неправильный:)

Проблема была в переменной recceiveData - она ​​была выпущена раньше. Марк предлагает выпустить его в методе dealloc объекта, который создает соединение, поэтому он заслуживает всяческих похвал за это!

Там есть одна небольшая вещь, которую нужно посмотреть - если вы освободите recceiveData в методе dealloc, вы потеряете память, если вызовете getMessages более одного раза. Вам нужно будет немного изменить getMessages следующим образом:

...
if (theConnection) {
    [recievedData release]; // If we've been here before, make sure it's freed.
    receivedData = [[NSMutableData data] retain];
} else {
...
1 голос
/ 13 ноября 2010

Комментируя JeremyP, где он говорит, что «В обоих следующих случаях вы нарушаете правила»: Шихан Алам следует коду Apple (фактически, cut'n'paste), найденному здесь .

Я также хотел бы добавить (а это то, на что не очень хорошо ответили здесь ), что «сборка и анализ» помечает «потенциальную утечку» в NSURLConnection (который инициируется с помощью "NSURLConnection alloc"). Но если кто-то вставит [theConnection release] в NSURLConnection, тем же способом, он потерпит крах.

Итак, у нас есть нечто, что, кажется, не поддается «правилам» управления памятью, но работает (afaik) и есть в документации Apple ..

0 голосов
/ 02 октября 2013

Хотя он не отвечает на полный вопрос, я несколько раз сталкивался с этой ошибкой, потому что я установил HTTPBody запроса в NSString вместо NSData. Xcode пытался предупредить меня.

0 голосов
/ 16 января 2012

Я получил EXC_BAD_ACCESS при асинхронном вызове в NSURLConnection. Код сгенерирован http://www.sudzc.com

Мне нужно было добавить удержание к

receivedData = [[NSMutableData data] retain];

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

  • , если я добавлю

    if ([response expectedContentLength] < 0) { NSLog(@"Connection error"); //here cancel your connection. [connection cancel]; return; }

чем все мои веб-сервисы отменены, в противном случае работает отлично.

...