I'm familiar with the __block
statement that makes the variable 'assignable' within a Block.
But I see that when using some of Objective-C features that uses Blocks as Arguments in Methods, some variables are assignable, even if they are not declared with this __block
statement.
Here are 2 codes for example:
[UIView animateWithDuration:2 animations:^
{
self.animatedView.backgroundColor = [UIColor blueColor];
self.animatedView.center = CGPointMake(100, 100);
}];
(animatedView is a simple UIView connected with an IBOutlet).
int myInt = 10;
NSMutableString* mString = [NSMutableString stringWithString:@"Mutable Hello"];
NSString* imString = @"Imutable Hello";
void (^myBlock)(void) = ^
{
[mString appendString:@" Block"]; //working
imString = @"Imutable Hello Block"; //error
myInt = 11; //error
};
My question is: How come I can assign values to the UIView instance properties?
I'm not addressing an Object and changing it, like my mString.
I would expect the 'center' property to behave like my myInt, as it's a C struct accessed directly, and not a pointer to an object.
I would expect 'backgroundColor' to behave like my imString, as it's a pointer to an object which is assigned with a new object, isn't it?
I couldn't find a satisfying explanation in the documentation... I would appreciate if anyone can provide one, or address me to one.
Blocks are a language-level feature added to C, Objective-C and C++, which allow you to create distinct segments of code that can be passed around to methods or functions as if they were values. Blocks are Objective-C objects, which means they can be added to collections like NSArray or NSDictionary .
__block is a storage qualifier that can be used in two ways: Marks that a variable lives in a storage that is shared between the lexical scope of the original variable and any blocks declared within that scope. And clang will generate a struct to represent this variable, and use this struct by reference(not by value).
Global variables are accessible, including static variables that exist within the enclosing lexical scope. Parameters passed to the block are accessible (just like parameters to a function).
Block scoped variables: A block scoped variable means that the variable defined within a block will not be accessible from outside the block. A block can reside inside a function, and a block scoped variable will not be available outside the block even if the block is inside a function.
This is the difference between assignment and usage. Usage being method calls. You are entirely permitted to call methods on an instance ([mString appendString:@" Block"]; //working
) but you can't assign (imString = @"Imutable Hello Block"; //error
) without tagging the variables to tell the compiler that it should enable it.
This code:
self.animatedView.backgroundColor = [UIColor blueColor];
is still not really an assignment, it's a 'hidden' method call. Dot notation is never an assignment, it's syntactic sugar for method calls. It actually translates to:
[[self animatedView] setBackgroundColor:[UIColor blueColor]];
The difference between assigning to local variables and to variables inside an object is the location in memory that they reside at. Basically, will they exist for long enough to be useful. It's the difference between data on the stack and on the heap.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With