1.block是一个特殊的OC对象, 它建立在栈上, 而不是堆上, 这么做一个是为性能考虑,还有就是方便访问局部变量.
2.默认情况下block使用到的局部变量都会被复制,而不是保留.所以它无法改变局部变量的值.
3.如果在变量面前加上__block, 那么编译器回去不会复制变量, 而是去找变量的地址, 通过地址来访问变量, 实际上就是直接操作变量.
4.另外块是在栈上分配的, 所以一旦离开作用域, 就会释放, 因此如果你要把块用在别的地方, 必须要复制一份.
所以在属性定义一个块的时候需要使用copy: @property (nonatomic, copy) void (^onTextEntered)(NSString *enteredText);
5.块是不能保留的, retain对块没有意义.
6.使用typed声明block typedef void(^didFinishBlock) (NSObject *ob);
这就声明了一个didFinishBlock类型的block,然后便可用@property (nonatomic,copy) didFinishBlock finishBlock;
声明一个block对象,注意对象属性设置为copy,接到block 参数时,便会自动复制一份。
__block是一种特殊类型,使用该关键字声明的局部变量,可以被block所改变,并且其在原函数中的值会被改变。
ARC和非ARC中block的区别:
ARC下Block何时会从栈自动被复制到推, 以及__block和__weak的使用问题
由于Block是默认建立在栈上, 所以如果离开方法作用域, Block就会被丢弃, 在非ARC情况下, 我们要返回一个Block ,需要 [Block copy];
在ARC下, 以下几种情况, Block会自动被从栈复制到堆:
1.被执行copy方法
2.作为方法返回值
3.将Block赋值给附有__strong修饰符的id类型的类或者Blcok类型成员变量时
4.在方法名中含有usingBlock的Cocoa框架方法或者GDC的API中传递的时候.
对于非ARC下, 为了防止循环引用, 我们使用__block来修饰在Block中实用的对象:
__block id blockSelf=self;
self.blk=^{
NSLog(@"%@",blockSelf); //在非ARC下对于栈上的_block对象, Block不会对其复制, 仅仅使用, 不会增加引用计数.
};
对于ARC下, 为了防止循环引用, 我们使用__weak来修饰在Block中实用的对象:
__weak id weakSelf=self;
self.blk=^{
NSLog(@"%@",weakSelf);
};
如果要在ARC下, 为了防止循环引用, 使用__block来修饰在Block中实用的对象,仍然会被retain, 所以需要多做一些设置
__block id blockSelf=self;
self.blk=^{
NSLog(@"%@",blockSelf);
self.blk=nil; //blk被释放, blk只有的blockSelf也就被释放了
};
blk(); //并且一定要运行一次, 否则不能被释放
这样就使blk断开了与blockSelf的持有关系.
这么多好处是可以自己控制对self的持有时间.
不过在最新的ios版本中, 这些会始终被已叹号形式提示存在循环引用问题.
这种书写方式不被推荐. 除非你要在block中修改__block的指针指向.
其实我们用使用__weak修饰符, 只是不能修改对象本身, 但是可以修改对象的属性.