我遇到过关键字'阻止'和'自我'似乎是关于保留周期。但这不是问题......
我的问题是:为什么在块外可见对self
的属性进行更改?我认为价值观应该被捕获&#39 ;?也就是说,块引用是原始对象的副本?
这里有一些代码来说明我的困境:
int a = 1;
self.someProperty.name = @"Foo";
[self.someProperty someMethodWithCompletionHandler:^() {
NSLog(@"%d", a);
NSLog(@"%@", self.someProperty.name);
}];
a = 2;
self.someProperty.name = @"Bar";
我得到的输出是:
1
Bar
答案 0 :(得分:2)
捕获值,这就是块中a
为1
的原因。
但你的字符串是一个对象。捕获指针(只是一个地址),但它指向的字符串的值已经改变。这就是你看“Bar”的原因。
答案 1 :(得分:2)
C,并且通过扩展,Objective-C使用按值语义。也就是说,当将参数传递给函数时,变量值的副本将传递给被调用者。允许被调用者更改本已复制的原始变量的方法是传递指针。被调用者现在可以直接访问原始变量引用的内存位置。
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;
}
Objective-C中的块以相同的方式工作。捕获的值与作为参数传递给函数的类型相同。这意味着传递非指针将不允许原始变量更改,而传递指针将允许更改这些位置的内存。由于对象只能通过指针访问,因此每个对象变量都是一个指针。这允许块以与上面示例中的g()
相同的方式操纵对象,可以操纵"原始" a
变量。