1.block的原理是怎样的?本质是什么?
block本质上也是一个OC对象,他内部也有一个isa指针。block是封装了函数调用以及函数调用环境的OC对象。
2.__block的作用是什么?有什么使用注意点?
外部属性修饰符:auto:局部变量。block结构体中会专门增加一个参数来存储变量的值。
static:
https://juejin.im/post/5b0181e15188254270643e88
在文章中的例子:全局变量或者静态全局变量,在生成的C++代码中是没有那两个参数的。在block中是直接访问的,是因为存储的地点就是你可以访问的。如果是局部变量,需要跨函数(block相当于是个函数)
当block中捕获对象类型的变量时,我们发现block结构体__main_block_impl_0的描述结构体__main_block_desc_0中多了两个参数copy和dispose函数
_Block_object_assign函数调用时机及作用
当block进行copy操作的时候就会自动调用__main_block_desc_0内部的__main_block_copy_0函数,__main_block_copy_0函数内部会调用_Block_object_assign函数。
_Block_object_assign函数会自动根据__main_block_impl_0结构体内部的person是什么类型的指针,对person对象产生强引用或者弱引用。可以理解为_Block_object_assign函数内部会对person进行引用计数器的操作,如果__main_block_impl_0结构体内person指针是__strong类型,则为强引用,引用计数+1,如果__main_block_impl_0结构体内person指针是__weak类型,则为弱引用,引用计数不变。
_Block_object_dispose函数调用时机及作用
当block从堆中移除时就会自动调用__main_block_desc_0中的__main_block_dispose_0函数,__main_block_dispose_0函数内部会调用_Block_object_dispose函数。
_Block_object_dispose会对person对象做释放操作,类似于release,也就是断开对person对象的引用,而person究竟是否被释放还是取决于person对象自己的引用计数。
总结
一旦block中捕获的变量为对象类型,block结构体中的__main_block_desc_0会出两个参数copy和dispose。因为访问的是个对象,block希望拥有这个对象,就需要对对象进行引用,也就是进行内存管理的操作。比如说对对象进行retarn操作,因此一旦block捕获的变量是对象类型就会会自动生成copy和dispose来对内部引用的对象进行内存管理。
当block内部访问了对象类型的auto变量时,如果block是在栈上,block内部不会对person产生强引用。不论block结构体内部的变量是__strong修饰还是__weak修饰,都不会对变量产生强引用。(MRC还是ARC?应该不论在什么环境下都是,因为)
如果block被拷贝到堆上。copy函数会调用_Block_object_assign函数,根据auto变量的修饰符(__strong,__weak,unsafe_unretained)做出相应的操作,形成强引用或者弱引用
如果block从堆中移除,dispose函数会调用_Block_object_dispose函数,自动释放引用的auto变量。
不论对象方法还是类方法都会默认将self作为参数传递给方法内部,既然是作为参数传入,那么self肯定是局部变量。参数就是局部变量。局部变量肯定会被block捕获。
访问了局部变量的block,在MRC中是NSStackBlock类型,在ARC中则是NSMallocBlock类型。
在ARC中,属性为assign和weak的block是NSStackBlock类型,
在ARC中,https://www.jianshu.com/p/19e6de8437f5 这篇文章更清晰,但是里面的NSGlobalBlock到底是放到了代码段还是数据段?
weak当对象为空时,会设置为nil;unsafe_unretained不会,但也是弱引用
block的属性修饰词为什么是copy?使用block有哪些使用注意?
block在修改NSMutableArray,需不需要添加__block?
不需要, NSMutableArray是通过地址传入的。就跟静态变量一样,static,传入的是指针,并没有用__block修饰。可以改变对象的内容,但是如果是改变的对象的地址,则是不允许的,必须使用__block.
ARC会在哪些情况下,自动对block进行一次copy操作?
1. block作为函数返回值时
2. 将block赋值给__strong指针时(可以用来对比属性的assign和weak)
3. block作为Cocoa API中方法名含有usingBlock的方法参数时
4. block作为GCD API的方法参数时
---------------------------------------------------
为什么要通过__forwarding获取age变量的值???
到此为止,__block为什么能修改变量的值已经很清晰了。__block将变量包装成对象,然后在把age封装在结构体里面,block内部存储的变量为结构体指针,也就可以通过指针找到内存地址进而修改变量的值。
__forwarding是指向自己的指针。这样的做法是为了方便内存管理,之后内存管理章节会详细解释。
在main函数中,直接创建了和__block相关的结构。
网友评论