iOS-Block初步探究

372 阅读2分钟

1)block分类

1、_NSConcreteGlobalBlock 全局的静态 block,不会访问任何外部变量;
2、_NSConcreteStackBlock 保存在栈中的 block,当函数返回时会被销毁;
3、_NSConcreteMallocBlock 保存在堆中的 block,当引用计数为0时会被销毁;

2)block对外部变量的引用

一、静态变量 和 全局变量 在加和不加 __block 都会直接引用变量地址。也就意味着 可以修改变量的值。在没有加__block 参数的情况下。   全局block 和 栈block 区别为 是否引用了外部变量,堆block 则是对栈block copy 得来。对全局block copy 不会有任何作用,返回的依然是全局block。

二,常量变量(NSString * a = @"hello";a 为常量变量,@“hello”为常量。)-----不加__block类型 block 会引用常量的地址(浅拷贝)。加__block类型 block会去引用常量变量(如:a变量,a = @"abc".可以任意修改a 指向的内容。)的地址。

三、对象变量 如(MyClass * class、Block block)。这里block 也是”类“对象(类似对象,其包含isa指针,clang 反编译可以查看。因为它不像从NSObject 继承下来的对象都支持 retain、copy、release)。   Block的copy、retain、release操作不同于NSObjec的copy、retain、release操作:   对Block不管是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1;   NSGlobalBlock:retain、copy、release操作都无效;   NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的错误是[[mutableAarry addObject:stackBlock],在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将stackBlock copy到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。   NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain;   尽量不要对Block使用retain操作。

3)block作为外部变量的时候,确保其被copy的场景

在ARC环境,大多数情况下编译器会适当地进行判断,会自动生成将Block从栈上复制到堆上的代码。 将Block作为函数返回值返回时,编译器会自动生成复制到堆上的代码。 编译器不能判断“自动将Block从栈上复制到堆上”的情况:向方法或函数的参数传递Block时