2010-05-10 10 views
6

Ich bin nicht wirklich sicher, warum mein Code ein EXC_BAD_ACCESS wirft, habe ich die Richtlinien in Apples Dokumentation folgt:Asynchronous NSURLConnection Wirft EXC_BAD_ACCESS

-(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!"); 
    } 

} 

Und meine Delegatmethoden

#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]; 
} 

ich eine EXC_BAD_ACCESS auf didReceiveData. Auch wenn diese Methode einfach einen NSLog enthält, erhalte ich den Fehler.

Hinweis: receivedData ist ein NSMutableData * in meiner Header-Datei

+0

Was sind Daten in der Zeile, die Ihre Variable 'receivedData' initialisiert? – Mark

Antwort

6

Verwenden NSZombieEnabled Bruchstelle und überprüfen, welche das freigesetzte Objekt ist.

Prüfen Sie auch:

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
{ 
    if ([response expectedContentLength] < 0) 
    { 
     NSLog(@"Connection error"); 
      //here cancel your connection. 
      [connection cancel]; 
     return; 
    } 
} 
+0

Zombie-Haltepunkt sagt: *** - [NSConcreteMutableData length]: Nachricht an freigegebene Instanz 0xd4af700 gesendet nicht sicher, wie zu diagnostizieren ... –

+0

, die in der connectionDidFinishLoading-Methode sein könnte, versuchen, den Code von dieser Methode zu entfernen.Wenn das das Problem ist, ist Ihre receivedData-Variable hier das Problem ... – Mark

+0

Ich habe den gesamten Code in connectionDidFinishLoading auskommentiert, und die App stürzt nicht mehr ab. Was denkst du ist falsch mit receivedData? –

2

Wenn Sie den Fehler auf didRecieveData unabhängig von dem Code innerhalb es sind immer, es sieht aus wie Ihre Stellvertretung befreit wurde?

Ich würde überprüfen, dass das Objekt, das die Methode getMessages enthält, nicht freigegeben (oder automatisch freigegeben) wird, bevor die Verbindung das Abrufen von Daten beendet hat.


EDIT: Die Kommentare unten zeigen, dass meine oben Antwort falsch ist :)

Das Problem war in der recievedData Variable - es früh freigegeben wurde. Mark schlägt vor, es in der Dealloc-Methode des Objekts zu veröffentlichen, das die Verbindung herstellt, so dass er dafür den ganzen Kredit verdient!

Es gibt eine kleine Sache zu suchen - wenn Sie die recievedData in der Dealloc-Methode freigeben, werden Sie Speicher verlieren, wenn Sie getMessages mehr als einmal aufrufen. Sie müssen getMessages dazu etwas ändern:

... 
if (theConnection) { 
    [recievedData release]; // If we've been here before, make sure it's freed. 
    receivedData = [[NSMutableData data] retain]; 
} else { 
... 
+0

Versuchen Sie auch nichts in den 'didRecieveData' zu tun, dh keine Codezeilen, nur eine leere Methode, die bestimmt, ob der Delegat freigegeben wird und nicht etwas anderes – Mark

+0

selbst wenn didReceiveData keine Codezeilen enthält, bekomme ich das gleiche Error. Der Delegierte ist er selbst. –

+0

machen Sie das gleiche mit 'didReceiveResponse' auch, sehen, ob das überhaupt hilft, das Problem einzugrenzen – Mark

5

Ich habe die Richtlinien in Apples Dokumentation folgt:

Das ist nicht wahr. In den beiden folgenden brechen Sie die Regeln:

- (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]; 
} 

In beiden Fällen Sie tun nicht das connection Objekt mit alloc erhalten, beginnt ein Verfahren mit new oder mit copy. Sie besitzen connection in diesen Methoden nicht. Sie dürfen es in diesen Methoden nicht freigeben.

Es scheint mir etwas zwielichtig, dass Sie ReceivedData auch dort veröffentlichen. Ich schlage vor, dass Sie die Instanzvariable sofort auf Null setzen, nachdem Sie sie freigegeben haben.

[receivedData release]; 
receivedData = nil; 

So wird es nicht versehentlich mehr als einmal freigegeben.

1

Kommentieren JeremyP, wo er sagt, dass "In beiden folgenden, brechen Sie die Regeln": Sheehan Alam folgt Apples Code (eigentlich cut'n'paste) gefunden here.

Ich möchte auch hinzufügen (und das ist etwas, das nicht gut beantwortet wurde here), dass die "Build und Analyse" ein "potentielles Leck" auf der NSURLConnection (die mit einem initiiert wird "NSURLConnection Alloc ] "). Aber wenn man eine [theConnection release] in die NSURLConnection einfügt, stürzt es mit derselben Methode ab.

So haben wir etwas, das die ‚Regeln‘ für die Speicherverwaltung zu trotzen scheint, noch Werke (afaik) und ist in Apples Dokumentation ..

2

habe ich den gleichen Fehler, wenn sie mit Gerät Debuggen obwohl es kein Problem war in der Simulation. Das Hinzufügen der folgenden Codezeile nach dem Loslassen receivedData das Problem gelöst:

receivedData = nil; 
0

Ich habe EXC_BAD_ACCESS auf Asynchronous Anruf bei NSURLConnection. Der Code von http://www.sudzc.com

erzeugt wird, ich brauchte eine behalten Methoden

receivedData = [[NSMutableData data] retain];

und die Callback nicht bekommen Signal schlechten Zugang mehr hinzuzufügen.

  • wenn ich die

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

hinzufügen als alle meine Web Service storniert werden, sonst funktioniert perfekt.

0

Während es die vollständige Frage nicht beantwortet, habe ich diesen Fehler ein paar Mal aufgetreten, weil ich die HTTPBody der Anfrage auf eine NSString statt einer NSData festgelegt. Xcode versuchte mich zu warnen.