Let’s say that I want to keep things nice and speedy in the main UI, so I break off slow parts into queues (using the global concurrent queues). Assume that selectedUser in this case remains static throughout.
In one View Controller I have something like this:
- (IBAction)buttonPressed:(id)sender {
User *selectedUser = [self getSelectedUser];
dispatch_queue_t queue;
queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
@autoreleasepool {
[userManager doSomething:selectedUser withForceOption:YES];
}
});
}
And in another class I have a singleton defined (userManager), with a method like this:
- (void)doSomething:(User*)user withForceOption:(BOOL)force {
SAppDelegate *delegate = (SAppDelegate *)[UIApplication sharedApplication].delegate;
extlib_main_queue = delegate.extlib_main_queue;
dispatch_async(extlib_main_queue, ^{
@autoreleasepool {
extlib_status_t status;
user.opIsStarting = YES;
extlib_call_id callId = -1;
// this is the part that worries me:
extlib_str_t uri = extlib_str((char *) [[NSString stringWithFormat:@"http:%@@%s", user.account,DOMAIN] UTF8String]);
status = extlib_call_make_call(0, &uri, 0, NULL, NULL, &callId);
}
});
}
My question is: is it safe to do this, or do I need to do something else to make sure that the passed User instance’s parameters remain accessible to both blocks?
You have nothing to worry about, because blocks retain the variables that they refer to.
The block in
buttonPressed:retainsselectedUsersince the block refers to it, and the block indoSomething:withForceOption:retainsuserbecause the block in there refers to it as well.Read this section of Blocks Programming Topics for more details on how this works.