美文网首页
底层8:block copy

底层8:block copy

作者: 张无奈 | 来源:发表于2020-08-31 00:33 被阅读0次

面试题:__block的作用是什么?有什么使用注意点?

使用__block,编译器会将__block变量包装成为一个对象,可以解决block内部无法修改auto变量值的问题。

注意点:内存管理方面,在mrc环境下是不会对oc对象产生强引用。

面试题:block的属性修饰词为什么是copy?使用block有哪些使用注意?

block一旦没有进行copy操作,就在栈上或者全局区,就不会在堆上,保证在堆上可以控制它的生命周期。

使用注意:循环引用问题

面试题:block在修饰NSMutableArray,需不需要添加_block?

不需要


在ARC环境下,编译器会根据情况自动将栈上的block复制到堆上,比如以下情况

1)block作为函数返回值时。

2)将block赋值给__strong指针时。

3)block作为Cocoa API中方法名含有usingBlock的方法参数时。

4)block作为GCD API的方法参数时。

对象类型auto变量

当block内部访问了对象类型的auto变量时

如果block在栈上

将不会对auto变量产生强引用。

如果block被拷贝到堆上:

会调用block内部的copy函数

copy函数内部会调用_Block_Object_assign函数

_Block_object_assign函数会根据auto变量的修饰符(__strong、__weak、__unsafe_unretained)做出相应的操作,类似retain(形成强引用,弱引用)

如果block从堆上移除

会调用block内部的dispose函数

dispose函数内部会调用_Block_object_dispose函数

_Block_object_dispose函数会自动释放引用的auto变量,类似release

栈上的Block复制到堆时,会调用copy函数

堆上的Block被废弃时,会调用dispose函数

什么时候释放,看强引用在哪儿。

block内部不能直接修改外部的auto变量,要修改需要以下:

方法1:可以用static修饰变量;

方法2:改成全局变量(永久占内存);

方法3:用__block修饰(而且没有修改变量的性质,即还是auto变量)。

__block修饰符

__block可以用于解决block内部无法修改auto变量值的问题。

__block不能修饰全局变量,静态变量(static)。

编译器会将__block变量包装成一个对象。(因为里面有一个isa指针,_forwording地址指向自己)

__weak问题解决

在使用clang转化OC为C++代码时,可能会遇到以下问题:

cannot create __weak reference in file using manual reference

解决方案:支持ARC,指定运行时系统版本,比如xcrun -sdk phones clang arch arm64 -objc -fobjc -arc -fobjc -runtime=iOS-8.0.0 main.m

__block的内存管理

当block在栈上时

并不会对__block变量产生强引用

当block被copy到堆时

会调用block内部的copy函数

copy函数内部会调用_Block_object_assign函数

_Block_object_assign函数会对__block变量形成强引用(retain)

当block从堆中移除时:

会调用block内部的dispose函数

dispose函数内部会调用_Block_object_dispose函数

_Block_object_dispose函数会自动释放引用的__block变量(release)

对象类型的auto变量、__block变量

eg:__block int age = 10; //对象类型__block变量

        NSObject *obj = [[NSObject alloc]init];//对象类型auto变量

       __weak NSObject *weakObj = obj;

       int型的变量是不能用__weak修饰的(__block __weak int age = 10;是错误的 ),只用于OC对象。

当block在栈上时,对它们都不会产生强引用。

当block拷贝到堆上时,都会通过copy函数来处理它们

__block变量(假设变量名为a)

__Block_object_assign((void *)&dst->a), (void *)src->a, 8 /* BLOCK_FIELD_IS_BYREF*/);

对象类型的auto变量(假设变量名为p)

__Block_object_assign((void *)&dst->p), (void *)src->p, 3 /* BLOCK_FIELD_IS_OBJECT*/);

当block从堆上移除时,都会通过dispose函数来释放它们。

__block变量(假设变量名为a)

__Block_object_dispose((void *)src->a), 8 /* BLOCK_FIELD_IS_BYREF*/);

对象类型的auto变量(假设变量名为p)

__Block_object_dispose((void *)src->p, 3 /* BLOCK_FIELD_IS_OBJECT*/);

auto变量、__block变量两者之前的相似差异:

相似:当block在栈上时,对它们都不会产生强引用;当block拷贝到堆上时,都会通过copy函数来处理它们;当block从堆上移除时,都会通过dispose函数来释放它们。

不同:在引用的问题上,__block产生的就是强引用,而如果是oc对象取决于当初怎么访问的,如果是弱引用访问就是弱引用,强引用访问就是强引用。

被__block修饰的对象类型

当__block变量在栈上时,不会对指向的对象产生强引用

当__block变量被copy到堆时

会调用__block变量内部的copy函数

copy函数内部会调用__Block_object_assign函数

__Block_object_assign函数会根据所指向对象的修饰符(__strong, __weak, __unsafe_unretained)做出相应操作,形成强引用(retain)或者弱引用(注意:这里仅限于ARC时会retain,MRC时不会retain

如果__block变量从堆上移除

会调用__block变量内部的dispose函数

dispose函数内部会调用_Block_object_dispose函数

_Block_object_dispose函数会自动释放指向的对象(release)

相关文章

  • 底层8:block copy

    面试题:__block的作用是什么?有什么使用注意点? 使用__block,编译器会将__block变量包装成为一...

  • Block底层代码

    这里只简单列举block底层用到的部分函数 _Block_copy _Block_byref_copy _Bloc...

  • iOS底层 - Block 的copy

    本文是通过学习优秀博客的记录整理与理解,然后以通俗简单的语句转述。引用到的地方如有遗漏或未能一一列举原文出处还望见...

  • iOS高级面试

    1、修饰属性有哪几个?追问 为什么用copy?weak对象为nil的底层原理?2、block是什么?block有几...

  • Copy 和 MutableCopy

    日志输出 Copy 和 MutableCopy block为什么要使用copy block使用copy是在MRC中...

  • Block

    1、如果没有对block进行copy操作,block存储于栈空间如果对block进行copy操作,block存储于...

  • block学习

    block为什么是用copy修饰 block属性的声明,首先需要用copy修饰符,因为只有copy后的block才...

  • block MRC&ARC

    block copy操作

  • OC中的copy

    1.所有被copy修饰的对象都会进行深copy吗? 答案:NO,例如block 全局block被copy修饰不会有...

  • Block 内存

    block的copy block的三种类型:NSConcreteStackBlock 存储于栈,copy时复制一份...

网友评论

      本文标题:底层8:block copy

      本文链接:https://www.haomeiwen.com/subject/gccjsktx.html