Why do I get a Random Crash during a Network Communication - (crash in CFRelease)?

2

I am working on one of my projects which is in maintenance phase so I do not have much liberty to change a major chunk at one go, While working on this I get to see this random crash on both Simulator as well as Device while the application Syncs with server. The Flow being Login-> Upload Local Data to Server -> Download data from Server.

enter image description here

The only point upto which I am able to debug is the screenshot I have attached from which I am not able to draw much of any inferences. enter image description here

The Network communication is facilitated via a Custom Class which is as follows

httpClient.h -------

#define TIMEOUT_SEC     30.0

@protocol HttpClientEventHandler_iPhone
@optional
- (void)requestSucceeded;
- (void)requestFailed:(NSError*)error;
@end

@class Reachability;
@interface HttpClient_iPhone : NSObject{
    NSURLConnection *connection;
    NSMutableData *recievedData;
    int statusCode; 
    id delegate;
    Reachability* hostReachable;
    BOOL networkChecked;
}
@property (nonatomic, retain) NSMutableString *previousRequest;
@property (readonly) NSMutableData *recievedData; // XX should be (readonly, retain)
@property (readonly) int statusCode;
@property (nonatomic, assign) id delegate;

+ (NSString*)stringEncodedWithBase64:(NSString*)str;
+ (NSString*) stringOfAuthorizationHeaderWithUsername:(NSString*)username password:(NSString*)password;
- (NSMutableURLRequest*)makeRequest:(NSString*)url;
- (NSMutableURLRequest*)makeRequest:(NSString*)url username:(NSString*)username password:(NSString*)password;
- (void)prepareWithRequest:(NSMutableURLRequest*)request;
- (void)requestGET:(NSString*)url;
- (void)requestPOST:(NSString*)url body:(NSString*)body type:(NSString*)type;
- (void)requestGET:(NSString*)url username:(NSString*)username password:(NSString*)password;
- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password body:(NSString*)body type:(NSString*)type;
- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password bodydata:(NSData*)body contenttype:(NSString*)type;
- (void)uploadImage:(NSString*)requesturl
           username:(NSString*)username
           password:(NSString*)password
          imagename:(NSString*)imagename 
        contenttype:(NSString*)contenttype
          imagedata:(NSData*)imagedata;

- (void)cancelTransaction;
- (void)reset;
- (BOOL)checkNetworkStatus;
@end

//HttpClient.m -----------

#import "HttpClient_iPhone.h"
#import "Base64.h"
#import "Reachability.h"
#import "SyncLiteral.h"

@implementation HttpClient_iPhone

@synthesize recievedData, statusCode;
@synthesize delegate,previousRequest;

- (id)init {
    if (self = [super init]) {
        [self reset];
        delegate = nil;
        networkChecked = NO;
    }
    return self;
}

- (void)dealloc {
    [connection release];
    [recievedData release];
    [super dealloc];
}

- (void)reset {
    [recievedData release];
    recievedData = [[NSMutableData alloc] init];
    [connection release];
    connection = nil;
    statusCode = 0; 
    networkChecked = NO;
}

+ (NSString*)stringEncodedWithBase64:(NSString*)str {
    static const char *tbl = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    const char *s = [str UTF8String];
    int length = [str length];
    char *tmp = malloc(length * 4 / 3 + 4);

    int i = 0;
    int n = 0;
    char *p = tmp;

    while (i < length) {
        n = s[i++];
        n *= 256;
        if (i < length) n += s[i];
        i++;
        n *= 256;
        if (i < length) n += s[i];
        i++;

        p[0] = tbl[((n & 0x00fc0000) >> 18)];
        p[1] = tbl[((n & 0x0003f000) >> 12)];
        p[2] = tbl[((n & 0x00000fc0) >>  6)];
        p[3] = tbl[((n & 0x0000003f) >>  0)];

        if (i > length) p[3] = '=';
        if (i > length + 1) p[2] = '=';
        p += 4;
    }
    *p = '\0';
    NSString *ret = [NSString stringWithCString:(const char*)tmp encoding: NSUTF8StringEncoding];
    free(tmp);
    return ret;
}

#pragma mark - HTTP Request creating methods

- (NSMutableURLRequest*)makeRequest:(NSString*)url {
    NSString *encodedUrl = (NSString*)CFURLCreateStringByAddingPercentEscapes(
                                                                              NULL, (CFStringRef)url, NULL, NULL, kCFStringEncodingUTF8);
    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
    [request setURL:[NSURL URLWithString:encodedUrl]];
    [request setCachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData];
    [request setTimeoutInterval:TIMEOUT_SEC];
    [request setHTTPShouldHandleCookies:FALSE];
    [encodedUrl release];
    return request;
}

- (NSMutableURLRequest*)makeRequest:(NSString*)url username:(NSString*)username password:(NSString*)password {
    NSMutableURLRequest *request = [self makeRequest:url];
    [request setValue:[HttpClient_iPhone stringOfAuthorizationHeaderWithUsername:username password:password]
   forHTTPHeaderField:@"Authorization"];
    return request;
}

+ (NSString*) stringOfAuthorizationHeaderWithUsername:(NSString*)username password:(NSString*)password {
    return [@"Basic " stringByAppendingString:[HttpClient_iPhone stringEncodedWithBase64:
                                               [NSString stringWithFormat:@"%@:%@", username, password]]];
}

- (void)prepareWithRequest:(NSMutableURLRequest*)request {
    // do nothing (for OAuthHttpClient)
}

#pragma mark -
#pragma mark HTTP Transaction management methods

/* Sending the Http Request for "GET" */
- (void)requestGET:(NSString*)url {

    //Reseting the http client
    [self reset];

    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSMutableURLRequest *request = [self makeRequest:url];
    [self prepareWithRequest:request];

    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"GET Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"\n\n\n"];

    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

/* Sending the Http Request for "POST" */
- (void)requestPOST:(NSString*)url body:(NSString*)body type:(NSString*)type {

    //Reseting the http client
    [self reset];
    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSMutableURLRequest *request = [self makeRequest:url];
    [request setHTTPMethod:@"POST"];
    if (type != nil && ![type isEqualToString:@""])
        [request setValue:type forHTTPHeaderField:@"Content-Type"]; 
    if (body) {
        [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Post Data - %@\n",body];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

/* Sending the Http Request for "GET" with username and password */
- (void)requestGET:(NSString*)url username:(NSString*)username password:(NSString*)password {
    //Reseting the http client
    [self reset];

    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSMutableURLRequest *request = [self makeRequest:url username:username password:password];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Authorization user - %@\n",username];
    [self.previousRequest appendFormat:@"Authorizating password - %@\n",password];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

/* Sending the Http Request for "POST" with username and password */
- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password body:(NSString*)body type:(NSString*)type {
    //Reseting the http client
    [self reset];
    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSMutableURLRequest *request = [self makeRequest:url username:username password:password];
    [request setHTTPMethod:@"POST"];
    if (type != nil && ![type isEqualToString:@""])
        [request setValue:type forHTTPHeaderField:@"Content-Type"]; 
    if (body) {
        [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Authorization user - %@\n",username];
    [self.previousRequest appendFormat:@"Authorizating password - %@\n",password];
    [self.previousRequest appendFormat:@"Post Data - %@\n",body];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

/* Sending the Http Request for "POST" with username and password */
- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password bodydata:(NSData*)body contenttype:(NSString*)type {
    //Reseting the http client
    [self reset];
    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSMutableURLRequest *request = [self makeRequest:url username:username password:password];
    [request setHTTPMethod:@"POST"];
    if (type != nil && ![type isEqualToString:@""])
        [request setValue:type forHTTPHeaderField:@"Content-Type"]; 
    if (body) {
        [request setHTTPBody:body];
    }
    if (body != nil && [body length] > 0){
        NSString* length_str = [NSString stringWithFormat:@"%d", [body length]];
        [request setValue:length_str forHTTPHeaderField:@"Content-Length"];
    }
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Authorization user - %@\n",username];
    [self.previousRequest appendFormat:@"Authorizating password - %@\n",password];
    [self.previousRequest appendFormat:@"Post Data - %@\n",[[[NSString alloc] initWithData:body encoding:NSUTF8StringEncoding]autorelease]];
    [self.previousRequest appendFormat:@"\n\n\n"];

    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

/* Sending the Http Request for uploading the image from database */
- (void)uploadImage:(NSString*)requesturl
           username:(NSString*)username
           password:(NSString*)password
          imagename:(NSString*)imagename 
        contenttype:(NSString*)contenttype
          imagedata:(NSData*)imagedata {

    //Reseting the http client
    [self reset];

    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    //Sending the http requqest
    NSString *boundary = @"---------------------------14737809831466499882746641449"; 
    NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; 
    NSURL *url = [NSURL URLWithString:requesturl];

    NSMutableURLRequest *request = [self makeRequest:requesturl username:username password:password];
    [request addValue:contentType forHTTPHeaderField: @"Content-Type"];

    NSMutableData *postbody = [NSMutableData data]; 
    [postbody appendData:[[NSString stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [postbody appendData:[[NSString stringWithFormat:@"Content-Disposition: form-data; name=\"uploadfile\"; filename=\"%@\"\r\n", imagename] dataUsingEncoding:NSUTF8StringEncoding]]; 
    [postbody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; 
    NSData* encoded_data = [Base64 encode:imagedata];
    [postbody appendData:[NSData dataWithData:encoded_data]];
    [postbody appendData:[[NSString stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; 

    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    [encoded_data release];
    [request setHTTPBody:postbody]; 
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

/* Canceling the HTTP Transaction */
- (void)cancelTransaction {
    [connection cancel];
    [self reset];
}

#pragma mark -
#pragma mark NSURLConnectionDelegate methods

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

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    statusCode = [(NSHTTPURLResponse*)response statusCode];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [recievedData appendData:data];
#ifdef _DEBUG
    NSLog(@"Receieved the http body data : \n%@\n", [[[NSString alloc] initWithData:data 
                                        encoding:NSASCIIStringEncoding] autorelease]);
#endif
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
#ifdef DEBUG
    NSLog(@"Receieved the http body data : \n%@\n", [[[NSString alloc] initWithData:recievedData
                                                                           encoding:NSASCIIStringEncoding] autorelease]);
#endif
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestSucceeded)]){
        [self.delegate performSelector:@selector(requestSucceeded) withObject:nil];
    }
    [self reset];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError*) error {
#ifdef _DEBUG   
    NSLog(@"didFailWithError \n %@",[error description]);
#endif
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
        [self.delegate performSelector:@selector(requestFailed:) withObject:error];
    }   
    [self reset];
}

//check network status chages
- (BOOL)checkNetworkStatus {
    BOOL result = NO;
    Reachability* reachability = [Reachability reachabilityWithHostName:SERVER_ADDRESS];
    NetworkStatus remoteHostStatus = [reachability currentReachabilityStatus];  

    if(remoteHostStatus == NotReachable) { 
#ifdef _DEBUG       
        NSLog(@"\nNetwork Status : not reachable\n");
#endif
        result = NO;
    }else if (remoteHostStatus == ReachableViaWWAN) { 
#ifdef _DEBUG       
        NSLog(@"\nNetwork Status : reachable via wwan\n");
#endif
        result = YES;
    }else if (remoteHostStatus == ReachableViaWiFi) { 
#ifdef _DEBUG
        NSLog(@"\nNetwork Status : reachable via wifi\n");
#endif
        result = YES;       
    }
    return result;
}

@end

If someone could guide me in right direction it will be of great help. The Project makes use of SDK 6.1 with Deployment target 4.3.

// EDIT to my question

The current implementation is as follows

@interface HttpClient_iPhone : NSObject{
    NSURLConnection *connection;
    NSMutableData *recievedData;
    int statusCode; 
    id delegate;
    Reachability* hostReachable;
    BOOL networkChecked;
}

@property (retain,atomic) NSMutableString *previousRequest;
@property (retain,readonly) NSMutableData *recievedData;
@property (readonly) int statusCode;
@property (nonatomic, assign) id delegate;

It's corresponding .m is now

@implementation HttpClient_iPhone

@synthesize recievedData, statusCode;
@synthesize delegate,previousRequest;

- (id)init {
    if (self = [super init]) {
        [self reset];
        delegate = nil;
        networkChecked = NO;
    }
    return self;
}

- (void)dealloc {
    if (connection) {
        [connection cancel];
    }
    [connection release];
    connection = nil;

    if (recievedData) {
        [recievedData release];
        recievedData = nil;
    }
    [super dealloc];
}

- (void)reset {
    if (recievedData) {
        [recievedData release];
        recievedData = nil;
    }

    recievedData = [[NSMutableData alloc] init];

    if (connection) {
        [connection cancel];
        [connection release];
        connection = nil;
    }
    statusCode = 0;
    networkChecked = NO;
}

- (void)requestGET:(NSString*)url {

    //Reseting the http client
    [self reset];

    //Checking the internet connection
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }

    NSMutableURLRequest *request = [self makeRequest:url];
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"GET Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"\n\n\n"];

    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

- (void)requestPOST:(NSString*)url body:(NSString*)body type:(NSString*)type {
    [self reset];
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    NSMutableURLRequest *request = [self makeRequest:url];
    [request setHTTPMethod:@"POST"];
    if (type != nil && ![type isEqualToString:@""])
        [request setValue:type forHTTPHeaderField:@"Content-Type"]; 
    if (body) {
        [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Post Data - %@\n",body];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

- (void)requestGET:(NSString*)url username:(NSString*)username password:(NSString*)password {
    [self reset];
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    NSMutableURLRequest *request = [self makeRequest:url username:username password:password];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Authorization user - %@\n",username];
    [self.previousRequest appendFormat:@"Authorizating password - %@\n",password];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
}

- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password body:(NSString*)body type:(NSString*)type {
    [self reset];
    if ([self checkNetworkStatus] == NO){
        if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
            [self.delegate performSelector:@selector(requestFailed:) withObject:nil];
        }       
        return;
    }
    NSMutableURLRequest *request = [self makeRequest:url username:username password:password];
    [request setHTTPMethod:@"POST"];
    if (type != nil && ![type isEqualToString:@""])
        [request setValue:type forHTTPHeaderField:@"Content-Type"]; 
    if (body) {
        [request setHTTPBody:[body dataUsingEncoding:NSUTF8StringEncoding]];
    }
    [self prepareWithRequest:request];
    if(![[url lastPathComponent] isEqualToString:@"pda_errorlogs"])
        self.previousRequest = [NSMutableString string];
    [self.previousRequest appendFormat:@"Post Requested API - %@\n",url];
    [self.previousRequest appendFormat:@"Authorization user - %@\n",username];
    [self.previousRequest appendFormat:@"Authorizating password - %@\n",password];
    [self.previousRequest appendFormat:@"Post Data - %@\n",body];
    [self.previousRequest appendFormat:@"\n\n\n"];
    connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
}

- (void)requestPOST:(NSString*)url username:(NSString*)username password:(NSString*)password bodydata:(NSData*)body contenttype:(NSString*)type {
    [self reset];
}

- (void)cancelTransaction {
    [self reset];
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    statusCode = [(NSHTTPURLResponse*)response statusCode];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [recievedData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestSucceeded)]){
        [self.delegate performSelector:@selector(requestSucceeded) withObject:nil];
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError*) error {
    if (self.delegate != nil && [self.delegate respondsToSelector:@selector(requestFailed:)]){
        [self.delegate performSelector:@selector(requestFailed:) withObject:error];
    }   
}

// Images for Crash Logs as reported on Crashlytics

Part 1 of 2 enter image description here

Part 2 of 2 enter image description here

iphone
ios
http
crash
nsurlconnection
asked on Stack Overflow May 17, 2013 by Rahul Sharma • edited Jul 25, 2013 by Rahul Sharma

2 Answers

2

Two comments:

1) change the recievedData property type in the header to "retain" (even though its not used as a property in your code)

2) before you release a NSURLConnection, you should send it cancel, ie [connection cancel]. You release it in dealloc and in reset. Also, make that cancel the first thing you do - don't go releasing data that might be used by it beforehand.

EDIT: based on your current code, your reset method still does cancel before it modifies the mutable data. I modified your code as you can see below, to mirror your dealloc method (where you don't need the nil statement):

- (void)reset {
    if (connection) {
        [connection cancel];
        [connection release];
        connection = nil;
    }
    if (recievedData) {
        [recievedData release];
        recievedData = nil;
    }

    recievedData = [[NSMutableData alloc] init];

    statusCode = 0;
    networkChecked = NO;
}

- (void)dealloc {
    if (connection) {
        [connection cancel];
        [connection release];
    }

    if (recievedData) {
        [recievedData release];
    }
    [super dealloc];
}

Try that.

answered on Stack Overflow May 17, 2013 by David H • edited Jul 24, 2013 by David H
2
  1. Run instruments with the Zombies instrument. Most of the time this will give you everything you need to troubleshoot an issue like this, though sometimes if you're hitting a bug deep within the framework it's not of much help. Looking at the information you've provided that is POSSIBLE but isn't likely. Adding a crash log would help.

  2. I would move away from using ivars and switch to using synthesized properties. Direct ivar access should only be done in init and dealloc - everywhere else, use the property.

  3. Make sure you have a good reason to implement an NSURLConnection delegate. If sendAsynchronousRequest:queue:completionHandler: meets your needs, use that - you won't have to deal with the complexities of a delegate. I have seen an awful lot of crashes occur because of mistakes made when people implement connection:didReceiveData: to buffer into an NSMutableData instance, or not handling cancel correctly (after cancel is called you will not get any more delegate callbacks - which may prevent your delegate from cleaning up properly).

  4. I see you are taking a username and password for each of these requests and it looks like you are building your own HTTP Basic authentication header. Don't. Instead use NSURLCredential to manage the authentication credentials. When NSURLConnection gets an authentication challenge it will look at the NSURLCredentialStorage for a credential to apply. This is seamless to your application and will save you a lot of potential pain. Here is a short example of how to create and set a credential. You only need to do this once, not for each connection:

    NSURLCredential         *credential         = nil;
    NSURLProtectionSpace    *protectionSpace    = nil;
    
    protectionSpace = [[NSURLProtectionSpace alloc] initWithHost:[url host] port:[[url port] integerValue] protocol:[url scheme] realm:nil authenticationMethod:NSURLAuthenticationMethodHTTPBasic];
    credential = [NSURLCredential credentialWithUser:username password:password persistence:NSURLCredentialPersistencePermanent];
    [[NSURLCredentialStorage sharedCredentialStorage] setDefaultCredential:credential forProtectionSpace:protectionSpace];
    [protectionSpace release];
    

Note that you have different persistence options available to you, NSURLCredentialPersistencePermanent will store the credential in the keychain permanently (you can remove it later if you want).

answered on Stack Overflow Jul 24, 2013 by quellish

User contributions licensed under CC BY-SA 3.0