问题
I'm using AFNetworking to perform URL request and defining success/error blocks within NSOperation - so that's basically running asynchronous process within NSOperation.
I understand the caveat behind this approach, being NSOperation would terminate prematurely before delegate methods are called and therefore have implemented one of the suggested solutions by running start() on the main thread (relevant post Asynchronous methods in NSOperation).
So far that's all good, I can see that the order of execution is correct i.e. success block executes, done, then dealloc gets called. UNTIL there's this (system?) thread called __destroy_helper_block that is referencing success block in the NSOperation which at this stage has been dealloc'd. What exactly is this? Is AFNetworking holding reference to the block?
Call stack on that thread is:
objc_release
_destroy_helper_block
_Block_release
__destroy_helper_block
_Block_release
start_wqthread
Code is
- (void) start {
...
void (^successHandler)(NSURLRequest *, NSHTTPURLResponse*, NSXMLParser *) = ^(NSURLRequest *request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
URLRequestParserDelegate *parserDelegate = [[URLRequestParserDelegate alloc]initWithChildDelegate:self];
// child to handle connection success
[self handleSuccess:request response:response];
// parse xml response data
[XMLParser setDelegate:parserDelegate];
[XMLParser parse];
[parserDelegate release];
[self finish];
}; // EXC_BAD_ACCESS on this line (?)
AFXMLRequestOperation *op = [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request
success:successHandler failure:nil];
[op start];
}
回答1:
I only know this is easily done with the ASINetworkQueue:
- (void) process {
//Create downloadQueue
if (![self queue]) {
[self setQueue:[[[ASINetworkQueue alloc] init] autorelease]];
[[self queue] setDelegate:self];
[[self queue] setShouldCancelAllRequestsOnFailure:NO];
[[self queue] setQueueDidFinishSelector:@selector(queueFinished:)];
}
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
__block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:@"http://www.YOURURL.com/"]];
[[self queue] addOperation:request]; //queue is an NSOperationQueue
NSLog(@"request added to operation");
[request setCompletionBlock:^{
NSLog(@"response headers %@", [request responseHeaders]);
NSLog(@"response body %@", [request responseString]);
}];
[request setFailedBlock:^{
NSLog(@"response error: %@", [[request error] localizedDescription]);
}];
}
- (void)queueFinished:(ASINetworkQueue *)queue{
NSLog(@"queueFinished:");
}
来源:https://stackoverflow.com/questions/9273954/blocks-within-nsoperation