Objective-c – Blocks and Variables

objective cobjective-c-blocks

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.

Best Answer

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

ARC, Blocks and Retain Cycles

blocks and ARC - copy or crash with release build (caused by optimization level)

Related Topic