سؤال

I've got a question about instance variables in combination with blocks & arc in Objective C with IOS5.

Shortly, when i access this code, the iPhone gives me an EXC_BAD_ACCESS and terminates:

- (void) doRequest: (void (^)(XMLTreeNode*) )completionHandler {
    NSString * urlString = [NSString stringWithFormat:@"blablaurl=%@&", action];

    for( NSString* key in parameters ){
        urlString = [urlString stringByAppendingFormat:@"&%@=%@", key, [parameters objectForKey:key]];
    }
    NSURL * url = [NSURL URLWithString:urlString];

    NSLog( @"Visiting: %@", [url absoluteString] );

    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPMethod:@"GET"];

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * response, NSData * data, NSError * err) {
            NSLog( @"Params=%@", parameters );
        completionHandler(e);
    }];
}

The exc_bad_access occurs on: NSLog( @"Params=%@", parameters );

(parameters is an instance variable of the class).. Just defined in the header file, no special property or what-so-ever..

Why does it crash and how can i prevent it? Thanks!

My guess is that it crashes because the objects lifetime is over after the doRequest call, and thus ARC cleans up all variables (and with that the parameter var).. When the urlconnection completes and calls the block, the instance variables are aready cleaned up..

هل كانت مفيدة؟

المحلول

parameters is clean up by ARC.

2 case here:

Your main object isn't released before the block completion: Just create an strong,nonatomic property for "parameters". Using the "strong" keyword in your property say to ARC that you need "parameters" during all your main object life

Your main object is released before the block completion: create a new __block pointer to your object

__block blockParameters = parameters;
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse * response, NSData * data, NSError * err) {
    NSLog( @"Params=%@", blockParameters );
    completionHandler(e);
}];

Using the "__block" keyword say to ARC that you need "blockParameters" during all your block life

نصائح أخرى

You have only the parameters of the block at your disposal, i.e. response, data and error in this case. You could use [response URL] to get at the parameters.

NSString *path = [[response URL] path];
NSString *secondPartOfURL = [[path componentsSeparatedByString:@"?"] objectAtIndex:1];
NSArray *keyValuePairs = [secondPartOfURL componentsSeparatedByString@´:@"&"];
NSMutableDictionary *parameters = [NSMutableDictionary dictionary];
for (NSString *pair in keyValuePairs) {
   NSArray *keyValue = [pair componentsSeparatedByString:@"="];
   [parameters setValue:[keyValue objectAtIndex:1] 
                 forKey:[keyValue objectAtIndex:0]];
}
NSLog(@"Params=%@", parameters);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top