Variables and Their Scope in Block Objects
Here is a brief summary of what you must know about variables in block objects:
-
Local variables in block objects work exactly the same as in Objective-C methods.
-
For inline block objects, local variables constitute not only variables defined withinthe block, but also the variables that have been defined in the method that imple-ments that block object. (Examples will come shortly.)
-
You cannotrefer toselfin independent block objects implemented in anObjective-C class. If you need to accessself,you must pass that object to the blockobject as a parameter. We will see an example of this soon.
-
You can refer to self in an inline block object only ifselfis present in the lexicalscope inside which the block object is created.
-
For inline block objects, local variables that are definedinsidethe block object’simplementation can be read from and written to. In other words, the block objecthas read-write access to variables defined inside the block object’s body.
-
For inline block objects, variables local to the Objective-C method that implementsthat block can only be read from, not written to. There is an exception, though: ablock object can write to such variables if they are defined with the __blockstoragetype. We will see an example of this as well.
-
Suppose you have an object of typeNSObjectand inside that object’s implemen-tation you are using a block object in conjunction with GCD. Inside this blockobject, you will have read-write access to declared properties of thatNSObjectinsidewhich your block is implemented.
-
You can access declared properties of yourNSObjectinside independent block ob-jectsonly ifyou use the setter and getter methods of these properties. You cannotaccess declared properties of an object using dot notation inside an independentblock object.
When it comes to inline block objects, there is oneveryimportant rule that you haveto remember: inline block objects copy the value for the variables in their lexical scope.If you don’t understand what that means, don’t worry. Let’s have a look at an example:
typedef void (^BlockWithNoParams)(void);
- (void) scopeTest{
NSUInteger integerValue = 10;
/*************** Definition of internal block object ***************/
BlockWithNoParams myBlock = ^{
NSLog(@"Integer value inside the block = %lu",(unsigned long)integerValue);
};
/*************** End definition of internal block object ***************/
integerValue = 20;
/* Call the block here after changing thevalue of the integerValue variable */
myBlock();
NSLog(@"Integer value outside the block = %lu",(unsigned long)integerValue);
}
We are declaring an integer local variable and initially assigning the value of 10 to it.We then implement our block object butdon’t call the block object yet.After the blockobject isimplemented,we simply change the value of the local variable that the blockobject will later try to read when we call it. Right after changing the local variable’svalue to 20, we call the block object. You would expect the block object to print thevalue 20 for the variable, but it won’t. It will print 10, as you can see here:
Integer value inside the block = 10Integer value outside the block = 20
(There is one exception to this:when a task is submitted to a concurrent or a serial queue using the dispatch_syncfunction, iOS will, if possible, run the task on the current thread, which might be themain thread, depending on where the code path is at the moment. This is an optimi-zation that has been programmed on GCD, as we shall soon see.)