Reputation: 13267
I'm trying to set and a NSURL using grand central dispatch, however it appears that the variable is set and accessible until you try to access it outside of the grand central dispatch block.
-(void)viewDidLoad {
[super viewDidLoad];
dispatch_queue_t backgroundQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(backgroundQueue,^{
self.ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSLog(@"ubiq inside: %@", self.ubiquitousURL);
if (self.ubiquitousURL) {
self.iCloudDocURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@Documents", self.ubiquitousURL]];
self.iCloudDocString = [self.iCloudDocURL absoluteString];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadFiles) name: UIApplicationDidBecomeActiveNotification object:nil];
} else {
/* change to the main queue if you want to do something with the UI. For example: */
dispatch_async(dispatch_get_main_queue(),^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Please enable iCloud" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
});
}
});
NSLog(@"ubiq outside: %@", self.ubiquitousURL);
}
The first NSLog
which, starts with ubiq inside
returns the correct URL, while ubiq outside
returns NULL. I'm using ARC, so no need to mention memory or anything similar... this is a GCD problem.
Do you know why self.ubiquitousURL
is not accessible outside of the GCD block? Thanks.
Upvotes: 0
Views: 522
Reputation: 14834
You are making async call. So this line NSLog(@"ubiq outside: %@", self.ubiquitousURL);
will get executed whether or not your code inside backgroundQueue is done.
You would see the outside log first then inside log.
Upvotes: 4
Reputation: 17861
dispatch_async
means "run this later". Thus, the code inside the block doesn't run immediately; it runs at some later time, after the "outside" NSLog
call has already been run. If you were to, for instance, put sleep(5)
before the NSLog
call, you would probably see the value. (You shouldn't really do that in the actual code, though; it would basically freeze the app for five seconds.)
If you want to run more code on the main queue after you've set that property, do something like this:
dispatch_async(backgroundQueue,^{
self.ubiquitousURL = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
NSLog(@"ubiq inside: %@", self.ubiquitousURL);
if (self.ubiquitousURL) {
self.iCloudDocURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@Documents", self.ubiquitousURL]];
self.iCloudDocString = [self.iCloudDocURL absoluteString];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(loadFiles) name: UIApplicationDidBecomeActiveNotification object:nil];
// ************** NEW HOTNESS HERE **************
dispatch_async(dispatch_get_main_queue(),^{
NSLog(@"ubiq outside: %@", self.ubiquitousURL);
});
} else {
/* change to the main queue if you want to do something with the UI. For example: */
dispatch_async(dispatch_get_main_queue(),^{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Please enable iCloud" message:nil delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil];
[alert show];
});
}
});
Replace that NSLog
line with a method call to do actual work if that's what you want to do once you've retrieved the iCloud URL.
Upvotes: 3