Well I have a serious problem. I have a class that manages connections with NSOperationQueue and delegate methods for that class that are actually NSURLConnection delegate methods. Sometimes, I have to pop the viewController that has the answer of my delegate class but it gets trapped in the scope of the delegate function, populating a UITableView and the app crashes just there. I solved it using @synchronized on the viewController dealloc and on the NSURLConnection delegates, but I don't think is the cleanest way since UI freezes sometimes when I'm adding a lot of info to the tableView. So, is there a way to do this clean?
- (void)viewDidLoad:(BOOL)animated {
[myManager startRequest];
}
//myManager class callback
- (void)managerDelegate {
//Doing things and just poped the viewController while in the function scope
//Program crashes, most of logs are "UIViewController message sent to deallocated instance"
}
//viewController dealloc
- (void)dealloc
{
@synchronized([Manager class])
{
alert.delegate = nil;
searchResultsTableView.delegate = nil;
searchResultsTableView.dataSource = nil;
[searchResultsTableView release]; searchResultsTableView = nil;
[serviceSearch release]; serviceSearch = nil;
[searchResults release]; searchResults = nil;
[XMLTag release]; XMLTag = nil;
[XMLParserServicesKeys release]; XMLParserServicesKeys = nil;
[XMLParserKeys release]; XMLParserKeys = nil;
[searchString release]; searchString = nil;
[__managedObjectContext release]; __managedObjectContext = nil;
manager.delegate = nil;
[manager stopAllRequests];
[manager release]; manager = nil;
[super dealloc];
}
}
Edit: some more code, now of myManager class
- (void) stopAllRequests
{
#ifdef _WSMANAGER_DEBUG_
NSLog(@"stopAllRequests %d", [connectionsArray count]);
#endif
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
for(NNSURLConnection* connection in connectionsArray)
{
[connection cancel];
[connection release];
}
[connectionsArray removeAllObjects];
[queue cancelAllOperations];
}
- (BOOL)startRequest
{
//Data initialization
NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(beginConnection:) object:[NSDictionary dictionaryWithObjectsAndKeys:request, kRequestKey, keyInfo, kUserInfoKey, nil]];
[queue addOperation:operation];
[operation release];
return YES;
}
-(void) beginConnection:(id)object
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NNSURLConnection* connection = [[NNSURLConnection alloc] initWithRequest:[object objectForKey:kRequestKey] delegate:self];
if(connection)
{
NSMutableData *requestData = [[NSMutableData alloc] init];
connection.url = [((NSURLRequest*)[object objectForKey:kRequestKey]) URL];
connection.userInfo = [NSDictionary dictionaryWithObjectsAndKeys:[object objectForKey:kUserInfoKey], kUserInfoKey, requestData, kRequestDataKey, nil];
[connectionsArray addObject:connection];
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];
}
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:TIMEOUT]];
if([connectionsArray indexOfObject:connection] != NSNotFound)
{
[connection cancel];
if([delegate conformsToProtocol:@protocol(ManagerDelegate)] && [delegate respondsToSelector:@selector(managerFailed:withKey:errorCode:)]) {
[delegate managerFailed:self withKey:[connection.userInfo objectForKey:kUserInfoKey] errorCode:ManagerErrorCodeTimeout];
if([connectionsArray count] < 1)
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
[connectionsArray removeObject:connection];
}
[pool drain];
}
- (void)connectionDidFinishLoading:(NNSURLConnection *)connection {
@synchronized([Manager class])
{
NSMutableData *requestData = [connection.userInfo objectForKey:kRequestDataKey];
NSString* responseString = [[NSString alloc] initWithData:requestData encoding:NSUTF8StringEncoding];
if([delegate conformsToProtocol:@protocol(PLMWSManagerDelegate)] && [delegate respondsToSelector:@selector(managerSuccess:responseString:withKey:)])
[delegate managerSuccess:self responseString:responseString withKey:[connection.userInfo objectForKey:kUserInfoKey]];
[responseString release];
[requestData release];
[connectionsArray removeObject:connection];
[connection cancel];
[connection release]; connection = nil;
if([connectionsArray count] < 1)
[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO];
}
}