Reputation: 79
At the moment I explore blocks opportunities, I read more then ten times apples docs) but i cant understand blocks behaviour in blogs examples and in my code. I know about __block modifier. So please look at few my examples, and say why it work or not:
1)Not working. Need __block, because I want to modified object.And self retained(correct?) and in blogs I'm frightened by retain cycle of self. Does it is?
NSDictionary *result = nil;
dispatch_async(queue, ^{
result = [self sendRequest:apiRequest];
});
2)Not working. I dont understand about variable scope of dispatch_async(dispatch_get_main_queue(), ^{});. Does it see all local variables in main thread or it is separate block from main thread, but exicuted in main thread? Like dispatch_async(dispatch_get_main_queue()^{}); copies all local variables in dispatch_async(queue,^{}); and switches semaphore to main thread.
NSDictionary *result = nil;
dispatch_async(queue, ^{
NSDictionary *data = [self sendRequest:apiRequest];
dispatch_async(dispatch_get_main_queue(), ^{
result=[data retain];
});
});
3)And examples from blogs and stanford's course that particularly muddle me, because they work.
- (void)viewWillAppear:(BOOL)animated
{
dispatch_queue_t downloadQueue = dispatch_queue_create(“image downloader”, NULL);
dispatch_async(downloadQueue, ^{
NSData *imageData = [NSData dataWithContentsOfURL:networkURL];
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
self.imageView.image = image;
self.imageView.frame = CGRectMake(0, 0, image.size.width, image.size.height);
 self.scrollView.contentSize = image.size;
});
});
dispatch_release(downloadQueue);
}
I dont understand, because first they dont mention about __block for self in the articles and the lessons, second this code modified variables, but through properties and complier doesn't swear that variables arent assignable and properties change reference, not value. Final it works. Thanks in advance.
Upvotes: 4
Views: 5747
Reputation: 187
Old question, but I feel like new readers might benefit from a more precise answer than the current one:
1) result
is a pointer to an object, not an object itself. Prepending __block
is necessary because that pointer is assigned to within the block. Modifying objects pointed to by pointer variables outside of the block is not the problem, e.g.
NSMutableDictionary* result = [NSMutableDictionary new];
and then modifying the object within the block via [result setObject...]
would be fine. And that's the reason why 3) works: Only variables of the object pointed to by self
are being modified. The pointer self
is never assigned to.
Regarding retainment under ARC of the objects referenced by the block, see e.g.:
ARC with blocks and retain cycles
blocks and ARC - copy or crash with release build (caused by optimization level)
Upvotes: 5
Reputation: 2062
1) Yes you'd need to declare:
__block NSDictionary *results = nil;
If you're using ARC it should automatically take care of retaining and releasing the results object. If not using ARC, then do a retain
as the first thing you do and a release
as the last thing you do in the block.
2) A block should have visibility of all variables/objects available to it's parent's scope. So in a method you should be able to see all local variables to that method and the object which that method belongs to (as self
).
3) Not too sure about this one. Variables do go away once you leave the function/method (which will be as so as most blocks have been called, rather than finished executing), where as anything that is part of self
won't. Maybe that has something to do with it.
Upvotes: 2