I'd suggest using NSOperationQueue and NSBlockOperation then you can cancel the operation in dealloc (or possibly viewWillDisappear) and within the block executing on GCD thread test isCanceled and exit / skip UI update. However you must ensure weak references to view controller or the execution block will retain the controller. Something like this:
// @property(nonatomic,weak) NSBlockOperation *backgroundOperation;
+ (NSOperationQueue*)operationQueue
{
static dispatch_once_t onceToken;
static NSOperationQueue *operationQueue;
dispatch_once(&onceToken, ^{
operationQueue = [[NSOperationQueue alloc] init];
});
return operationQueue;
}
- (NSOperationQueue*)operationQueue
{
return [[self class] operationQueue];
}
- (void)dealloc
{
[self.backgroundOperation cancel];
}
- (void)getInfo
{
NSDictionary *places = [[NSDictionary alloc] initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"places" ofType:@"plist"]];
NSArray *placescc = [[NSArray alloc] initWithArray:places.allKeys];
__block NSUInteger placewaiting = placescc.count;
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSDictionary *savedLocs = [[defaults objectForKey:@"savedLocs"]mutableCopy]; //got savedLocs
NSDictionary *thisLoc = [[savedLocs objectForKey:_LocId]mutableCopy]; //got this Loc
lastInfoCount = 0; // set default
if ([[thisLoc objectForKey:@"Infos"]count]){
lastInfoCount = [[thisLoc objectForKey:@"Infos"]count]; // set saved count if we have one
}
// Ensure previous operation finished
[self.backgroundOperation cancel];
NSBlockOperation *op = [[NSBlockOperation alloc] init];
self.backgroundOperation = op;
__weak NSBlockOperation *weakOp = op;
__weak typeof(self) weakSelf = self;
[op addExecutionBlock:^{
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://url.com/%@/%@",place, LocIdString]];
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:url];
if (weakOp && !weakOp.isCancelled)
{
dispatch_async(dispatch_get_main_queue(), ^{
[parser setDelegate:weakSelf];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
placewaiting = placewaiting-1;
if (placewaiting == 0){
[weakSelf.tableView reloadData];
[weakSelf.activityIndicator stopAnimating];
lastRefresh = [NSString stringWithFormat:@"%@",[NSDate date]];
}
});
}
}];
[[self operationQueue] addOperation:op];
}
Note that weakSelf, weakOp and backgroundOperation property will auto-null when their referenced objects are released so if UI update code in block ever executes after view controller dismissed weakSelf.tableView/activityIndicator will be null and a no op. In your case since most of the work is in retrieving and parsing the data synchronously so that won't be aborted but the above code means the view controller will be released immediately and UI updates on the view controller become no-ops.