Blocks and Variables

I am currently exploring the possibilities of blocks, I read apples docs more than ten times), but I can not understand the behavior of blocks in the blog examples and in my code. I know about the __block modifier. So please look at a few of my examples and tell me why this works or not:

1) Doesn't work. I need a __ block, because I want to change the object. And I keep it (right?), And on the blogs I got scared, keeping the cycle myself. This is true?

NSDictionary *result = nil; dispatch_async(queue, ^{ result = [self sendRequest:apiRequest]; }); 

2) Doesn't work. I do not understand about the scope variable dispatch_async (dispatch_get_main_queue (), ^ {}) ;. Does he see all local variables in the main thread or a separate block from the main thread, but is called in the main thread? For example dispatch_async (dispatch_get_main_queue () ^ {}); copies all local variables to dispatch_async (queue, ^ {}); and switches the semaphore to the 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 Stanford's blogs and course, which especially confuse 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 don’t understand, because at first they did not mention __block for themselves in articles and lessons, secondly, this code modified the variables, but through the properties and complier did not swear that the variables arent assigned and the properties change the link, not the value. The final is working. Thanks in advance.

+4
source share
2 answers

1) Yes, you need to declare:

 __block NSDictionary *results = nil; 

If you use ARC, it should automatically take care of saving and releasing the result object. If you are not using ARC, do retain as the first thing you do, and release is the last thing you do in the block.

2) The block must have the visibility of all variables / objects available to it by the parent area. Thus, in the method you should be able to see all the local variables for this method and the object to which this method belongs (as self ).

3) Not too sure about this. The variables go away as soon as you leave the function / method (it will be as if most of the blocks were , called , and not finished execution), where everything that is part of self will not be, Perhaps this has something to do with to this.

+2
source

An old question, but I feel that new readers can get a more accurate answer than the current one:

1) result is a pointer to an object, not an object. Preliminary preparation of __block necessary because this pointer is assigned inside the block. Changing the objects pointed to by pointers outside the block is not a problem, for example.

 NSMutableDictionary* result = [NSMutableDictionary new]; 

and then changing the object in the block using [result setObject...] will be fine. And that is the reason why 3) works: only the object variables that self points to change. The self pointer is never assigned.

Regarding the receipt in ARC of the objects referenced by the block, see, for example:

ARC with blocks and save cycles

ARC, blocks, and persistent loops

blocks and ARC - copying or crash when creating a release (caused by optimization level)

+5
source

Source: https://habr.com/ru/post/1395734/


All Articles