iOS中block的简单使用及注意点

block是一个匿名函数,也是一个特殊的Objective-C对象。做为Objective-C对象的block是设置在栈上的,属于_NSConcreteStackBlock类。做为属性时,一般使用copy来修饰,将其复制到堆上,栈区的变量是由编译器负责分配和释放的。变量的作用域结束时,栈上的__block变量和block都会被废弃,而复制到堆上的__block变量和block在变量作用域结束时不受影响,可以正常的进行访问,因为__block变量可以通过结构体成员变量__forwarding实现无论是在栈上还是堆上都能够正确的访问。

在OC中,block被分为以下3类:_NSConcreteStackBlock、_NSConcreteGlobalBlock、_NSConcreteMallocBlock。


1.block访问外部变量
在block内部可以访问block的外部变量,但不可修改block外部的变量。
如果直接在block内部修改外部变量时会报错:

使用 __block修饰符修饰block的外部变量后,就可以在block内部修改外部变量:

在block中可以存有超过其变量作用域的被截获对象的自动变量。变量作用域结束时,原来的自动变量被废弃,block中超过变量作用域的存在的变量,将不能通过指针访问原来的自动变量。使用 __block修饰的自动变量,可以在block内部修改,是因为改变了变量的作用域。

2.block使用的循环引用
使用block时要注意由持续循环引用导致内存泄露。造成循环引用的原因是block和self之间相互强引用,self持有block,block持有self。


一般情况下,在使用block的时候,都会使用__weak对self进行修饰来避免出现循环引用的情况:

不是所有使用block的情况都要用__weak来修饰self,只有self直接或者间接使用block时才需要使用__weak修饰self,避免出现循环引用。

UIView动画方法和GCD延时方法中都使用了block,此时并未使用__weak对self进行修饰,也没有造成循环引用。

猜你喜欢

转载自blog.csdn.net/yeyu_wuhen/article/details/78799258