Reputation: 2294
Every thread I've come across with keywords 'block' and 'self' seem to be in regards to retain cycles. But that's not the issue here...
My question is: Why are changes made to properties of self
outside the block visible in the block? I thought values were meant to be 'captured'? That is, what the block references is a copy of the original object?
Here's a bit of code to illustrate my dilemma:
int a = 1;
self.someProperty.name = @"Foo";
[self.someProperty someMethodWithCompletionHandler:^() {
NSLog(@"%d", a);
NSLog(@"%@", self.someProperty.name);
}];
a = 2;
self.someProperty.name = @"Bar";
The output I get is:
1
Bar
Upvotes: 1
Views: 463
Reputation: 7552
C, and by extension, Objective-C uses by-value semantics. That is, when passing parameters to a function, a copy of the variable's value is passed to the callee. The way to allow the callee to change the original variable that would have been copied is to pass a pointer. The callee now has a way to directly access the memory location referred to by the original variable.
int a = 1; // a is stored at memory location 0xABCD
f(a); // The value of a (1) is passed to f(). This copy is at 0xCDEF.
void f(int a) {
// The value at 0xCDEF is now 10, but 0xABCD (the "original") is untouched.
a = 10;
}
g(&a); // The address of "a" is passed. This is the value 0xABCD.
void g(int *a) {
// This dereferences the pointer and changes the value at that location to 10.
// As the value of the pointer is the address of "a", the original variable "a"
// now has the new value of 10.
*a = 10;
}
Blocks in Objective-C work the same way. The captured values are the same sort that would have been passed as parameters to a function. This means that passing non-pointers will not allow the original variable to change, while passing pointers will allow the memory at those locations to be altered. As objects can only be accessed through pointers, every object variable is a pointer. This allows the block to manipulate the object the same way g()
in the example above can manipulate the "original" a
variable.
Upvotes: 2
Reputation: 1654
Values are captured, that's why a
is 1
inside the block.
But your string is an object. The pointer (just an address really) is captured but the value of the string it is pointing to has changed. That's why you see "Bar".
Upvotes: 2