Reputation: 420
I am very new to the GCD approach. I am trying to sync data from the Internet using blocks in GCD. I have a situation where if the sync operation is in progress, and the network fails then my application crashes. When not using blocks, I am able to handle that by using the @try/@catch method. But when I am trying to do it with blocks and GCD, I am not able to handle the crash or the exception. Any ideas on how to handle the crash?
Calling sync accounts in the block:
dispatch_async(exampleQueue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncStatusUpdate:@"Loading Accounts"];
});
[AccountService syncAccounts];
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"accountsFirstSyncCompleted"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
-[AccountService syncAccounts] method:
@try {
ZKDescribeSObject *accountDescription = [app.client describeSObject:@"Account"];
NSString *query = [NSString stringWithFormat:@"Select %@ From Account Where LastModifiedDate > %@", [accountDescription fieldsAsCsv], [dateTimeFormatter stringFromDate:lastSyncDate]];
ZKQueryResult *result = [[app.client query:query batchSize:[NSNumber numberWithInt:200]] retain];
}
@catch (ZKSoapException *e) {
[RootViewController hadSyncError:e];
}
I am not able to catch the exception that occurs when we go offline while syncing.
Upvotes: 3
Views: 1976
Reputation: 29886
This is totally doable. As a commenter suggests you can use @try/@catch in blocks without incident. Using your code, for example:
dispatch_async(exampleQueue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncStatusUpdate:@"Loading Accounts"];
});
BOOL error = NO;
@try {
// I pasted this code in line, but you could take the @try/@catch out of the
// syncAccounts method, and just let the exception bubble up to here.
ZKDescribeSObject *accountDescription = [app.client describeSObject:@"Account"];
NSString *query = [NSString stringWithFormat:@"Select %@ From Account Where LastModifiedDate > %@", [accountDescription fieldsAsCsv], [dateTimeFormatter stringFromDate:lastSyncDate]];
ZKQueryResult *result = [[app.client query:query batchSize:[NSNumber numberWithInt:200]] retain];
}
@catch (ZKSoapException *e)
{
dispatch_async(dispatch_get_main_queue(), ^{
[RootViewController hadSyncError:e];
});
error = YES;
}
if (error)
{
dispatch_async(dispatch_get_main_queue(), ^{
[self sendSyncStatusUpdate:@"Failed to Sync Accounts!"];
});
return;
}
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"accountsFirstSyncCompleted"];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
This is a perfectly fine way to use GCD.
Upvotes: 2