Асинхронный NSURLConnection бросает EXC_BAD_ACCESS

Я не действительно уверен, почему мой код бросает 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, я получаю ошибку.

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

6
задан Sheehan Alam 10 May 2010 в 11:22
поделиться

3 ответа

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

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

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    if ([response expectedContentLength] < 0)
    {
        NSLog(@"Connection error");
            //here cancel your connection.
            [connection cancel];
        return;
    }
}
6
ответ дан 8 December 2019 в 14:41
поделиться

Я следовал рекомендациям в документации 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];
}

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

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

[receivedData release];
receivedData = nil;

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

5
ответ дан 8 December 2019 в 14:41
поделиться

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

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


EDIT: Комментарии ниже показывают, что мой ответ неверен :)

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

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

...
if (theConnection) {
    [recievedData release]; // If we've been here before, make sure it's freed.
    receivedData = [[NSMutableData data] retain];
} else {
...
2
ответ дан 8 December 2019 в 14:41
поделиться