Block实现原理
要想知道Block的内部实现,需要知道Block编译完后是什么样子,使用clang可看到Block编译完后的代码实现。
Block的语法看着特别,但它实际上是作为极普通的C语言源代码来处理的。通过支持Block的编译器,将含有Block语法的源代码转换为C语言的源代码,并作为极为普通的C语言源代码被编译。
clang -rewrite-objc 文件名
Block实质就是: 编译的时候编译器会把Block的表达式及Block变量,编译成一般的C语言结构体、函数,block调用就是函数指针调用。Block表达式中使用局部变量时,编译生成的结构体(__main_block_impl_0)会持有该变量,该结构体会带着默认值初始化结构体实例。
可以用一句话来表示Blocks的扩充功能:带有自动变量(局部变量)的匿名函数。
参考:
ARC情况下
1.如果用copy修饰Block,该Block就会存储在堆空间。则会对Block的内部对象进行强引用,导致循环引用。内存无法释放。解决方法:新建一个指针(__weak typeof(Target) weakTarget = Target )指向Block代码块里的对象,然后用weakTarget进行操作。就可以解决循环引用问题。
2.如果用weak修饰Block,该Block就会存放在栈空间。不会出现循环引用问题。
MRC情况下用copy修饰后,如果要在Block内部使用对象,则需要进行(__block typeof(Target) blockTarget = Target )处理。在Block里面用blockTarget进行操作。
声明block的时候实际上是把当时的临时变量又复制了一份,在block里即使修改了这些复制的变量,也不影响外面的原始变量。即所谓的闭包。
但是当变量是一个指针的时候,block里只是复制了一份这个指针,两个指针指向同一个地址。所以,在block里面对指针指向内容做的修改,在block外面也一样生效。
__weak __typeof(&*self)weakSelf =self; 等同于
__weak UIViewController *weakSelf =self;
__strong typeof(self) strongSelf = weakSelf; 在块语法内部调用
为什么不用__block 是因为通过引用来访问self的实例变量 ,self被retain,block也是一个强引用,引起循环引用,用__week是弱引用,当self释放时,weakSelf已经等于nil。
__block 为了改变block代码块外部的变量。
__weak 是为了防止循环引用(memory cycle),引起内存泄露的问题。不会影响对象的释放, 对象在被释放的同时,指向它的弱引用会自动被置nil
strong所声明的变量将成为对象的持有者;引用计数+1
weak 所声明的变量将没有对象的所有权,对象可以自动赋值nil;引用计数不变
copy 所声明的变量是拷贝对象的持有者。引用计数+1













网友评论