ios中的block
来源:互联网 发布:淘宝领券怎么领取 编辑:程序博客网 时间:2024/06/01 08:13
1.block的实质
Block的实质就是一个结构体
我们可以通过clang -rewrite-objc .m文件将oc的.m文件转换为c++的.cpp文件,来查看block的实质
例:
打开main.cpp
2.block存放位置和使用copy
因为block实质上是一个结构体,所以block默认是放到栈中,所以默认情况下block的生命周期比较短,会被自动释放,如果想让block不被自动释放,则需要将block放到堆中,而只有copy才能使block代码拷贝到堆中,其他修饰都不能,所以我们在声明block成员变量时应该使用copy,保证类的实例对象在,则block也在
例:
3.block线程安全
Block是线程安全的,他会将外部访问变量进行拷贝一份,避免被无意中修改
例:
例:
而使用__block后,会禁止block拷贝
例:
其实上面的有__block和没有__block是很好理解的,结合前面的block实质的分析,block是一个结构体,而他的实例是通过调用该结构体的构造函数来创建的,在函数中如何改变外部传递的变量的值?只有将它的地址传递进来,所以查看c++源码可以发现__block确实传递的是a的地址,而没有__block的是直接传递a的值
如下:
带有__block的
不带有__block的:
4.block的循环引用问题
Block循环引用是值block代码块中引用了外部对象,而外部对象又同时引用了block,此时就会出现循环引用
例:
从上图看出,block被拷贝到堆中,Person中的operation变量对block有强引用,而block对person有强引用,所以造成循环引用了
解决方法是:将block访问的外部对象使用__weak或者____unsafe_unretained
例:
第二种比较隐晦的循环引用
例:
这种循环引用经常会被忽略
Block的实质就是一个结构体
我们可以通过clang -rewrite-objc .m文件将oc的.m文件转换为c++的.cpp文件,来查看block的实质
例:
int main(int argc, const char * argv[]) { @autoreleasepool { //1.默认情况下block会将外部变量先copy一份,考虑多线程问题 int a = 10; void (^op)() = ^{ NSLog(@"%d",a);//此时输出的是10,因为这里的a被copy了一份 }; a = 100; op(); } return 0;}
打开main.cpp
2.block存放位置和使用copy
因为block实质上是一个结构体,所以block默认是放到栈中,所以默认情况下block的生命周期比较短,会被自动释放,如果想让block不被自动释放,则需要将block放到堆中,而只有copy才能使block代码拷贝到堆中,其他修饰都不能,所以我们在声明block成员变量时应该使用copy,保证类的实例对象在,则block也在
例:
#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic, copy) void (^operation)();@end
3.block线程安全
Block是线程安全的,他会将外部访问变量进行拷贝一份,避免被无意中修改
例:
例:
int main(int argc, const char * argv[]) { @autoreleasepool { int a = 10; void (^block)() = ^{ NSLog(@"%d",a);//这里a会被拷贝一份 }; //这里a被修改为100了,但是block中的a已不再是外部的a了,他已经被拷贝了一份 a = 100; block(); } return 0;}
而使用__block后,会禁止block拷贝
例:
int main(int argc, const char * argv[]) { @autoreleasepool { __block int a = 10;//这里表明a变量不会被拷贝 void (^block)() = ^{ NSLog(@"%d",a); }; a = 100; block(); } return 0;}
其实上面的有__block和没有__block是很好理解的,结合前面的block实质的分析,block是一个结构体,而他的实例是通过调用该结构体的构造函数来创建的,在函数中如何改变外部传递的变量的值?只有将它的地址传递进来,所以查看c++源码可以发现__block确实传递的是a的地址,而没有__block的是直接传递a的值
如下:
带有__block的
不带有__block的:
4.block的循环引用问题
Block循环引用是值block代码块中引用了外部对象,而外部对象又同时引用了block,此时就会出现循环引用
例:
int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init]; person.name = @"张三"; [person setOperation:^{ NSLog(@"%@",person.name);//这里会造成循环引用 }]; } return 0;}
从上图看出,block被拷贝到堆中,Person中的operation变量对block有强引用,而block对person有强引用,所以造成循环引用了
解决方法是:将block访问的外部对象使用__weak或者____unsafe_unretained
例:
int main(int argc, const char * argv[]) { @autoreleasepool { Person *person = [[Person alloc] init]; person.name = @"张三"; __weak typeof(person) weakPerson = person; [person setOperation:^{ NSLog(@"%@",weakPerson.name);//这里会造成循环引用 }]; } return 0;}
第二种比较隐晦的循环引用
例:
- (instancetype)init{ if (self = [super init]) { [self setOperation:^{ _name = @"sss";//这里也会造成循环引用,因为_name就是self->name }]; } return self;}
这种循环引用经常会被忽略
0 0
- ios中的block
- ios中的block
- IOS中的block
- iOS中的 Block
- iOS中的Block
- IOS中的block
- ios中的block
- iOS 中的block异常
- iOS中的block全面分析
- IOS中的Block的使用
- iOS中的代理和Block
- IOS中的Block在C++中的运用
- IOS中的Block在C++中的运用
- iOS中的block(block编程官方文档翻译)
- iOS中的block和retain cycle (经典)
- IOS中的block和retain cycle
- IOS中的block和retain cycle
- IOS中的block和retain cycle (经典)
- fjfjjffjddd
- XListView 使用笔记
- 压敏电阻
- CvTHaarFeature和CvFastHaarFeature以及CvIntHaarFeatures的区别
- 黑马程序员——IO流(一)
- ios中的block
- libevent使用(一)-----基础配置
- 利用jsoncpp库处理json格式数据
- 二、在Eclipse中体验Date日期类
- XE8 (RTM) Android SDK 更新安装,xe8android
- ios_swift开发资源整理
- 服务器备份工具
- TCP的拥塞控制
- Android版本和API Level的对应关系