__block变量和对象的完美兼容解读
2023-11-14 18:24:47
__block变量和对象的兼容性
在之前的文章[iOS]Block系列探究二 - 捕获变量中,我们讨论过__block是如何处理基础类型的局部变量使block内部可以修改局部变量的。这篇文章我们仔细研究下__block说明符修饰变量和对象。
首先我们研究一下__block说明符修饰局部变量。不多说,直接上OC代码:
int main(int argc, const char * argv[]) {
__block int num = 10;
void (^block)(void) = ^{
num++;
printf("num = %d\n", num);
};
block();
return 0;
}
运行结果:
num = 11
从结果可以看出,block内部可以修改局部变量num的值。这是因为__block说明符告诉编译器,这个局部变量可能被block捕获,编译器会为这个局部变量分配一块内存,这个内存的地址不会随着block的执行而改变,这样block内部就可以通过这个地址来修改局部变量的值。
接下来我们研究一下__block说明符修饰对象。我们还是上代码:
int main(int argc, const char * argv[]) {
__block NSString *str = @"hello";
void (^block)(void) = ^{
str = @"world";
printf("str = %@\n", str);
};
block();
return 0;
}
运行结果:
str = world
从结果可以看出,block内部也可以修改对象str的值。这是因为__block说明符告诉编译器,这个对象可能被block捕获,编译器会为这个对象分配一块内存,这个内存的地址不会随着block的执行而改变,这样block内部就可以通过这个地址来修改对象的值。
需要注意的是,__block说明符只能修饰局部变量和对象,不能修饰全局变量和静态变量。这是因为全局变量和静态变量的地址是固定的,不会随着block的执行而改变,因此不需要使用__block说明符来告诉编译器。
__block变量和对象的内存管理
__block变量和对象的内存管理与普通变量和对象有所不同。普通变量和对象在block执行结束后,其内存会被自动释放。而__block变量和对象的内存不会被自动释放,需要手动释放。这是因为__block变量和对象被block捕获,block执行结束后,这些变量和对象仍然存在于内存中。如果我们不手动释放这些变量和对象的内存,就会造成内存泄漏。
__block变量和对象的内存释放方式与普通变量和对象相同,可以使用release方法来释放内存。例如:
__block NSString *str = @"hello";
void (^block)(void) = ^{
str = @"world";
printf("str = %@\n", str);
};
block();
[str release];
在block执行结束后,我们使用[str release]方法来释放str对象的内存。
总结
__block变量和对象可以被block捕获,block内部可以修改这些变量和对象的值。__block变量和对象的内存管理与普通变量和对象有所不同,需要手动释放内存。