美文网首页
Block汇总

Block汇总

作者: 冰山_X | 来源:发表于2021-06-15 10:43 被阅读0次

1 Block的底层原理?

//用于描述块对象的>标志 flags
enum {
BLOCK_DEALLOCATING = (0x0001), // runtime
BLOCK_REFCOUNT_MASK = (0xfffe), // runtime
BLOCK_NEEDS_FREE = (1 << 24), // runtime
BLOCK_HAS_COPY_DISPOSE = (1 << 25), // compiler
BLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ code
BLOCK_IS_GC = (1 << 27), // runtime
BLOCK_IS_GLOBAL = (1 << 28), // compiler
BLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATURE
BLOCK_HAS_SIGNATURE = (1 << 30), // compiler
BLOCK_HAS_EXTENDED_LAYOUT=(1 << 31) // compiler
};

//block的底层结构
struct Block_layout {
void *isa; //isa指针,8字节
volatile int32_t flags; //上面的枚举
int32_t reserved;
BlockInvokeFunction invoke;//调用函数
struct Block_descriptor_1 *descriptor;
//descriptor:此变量为可变,根据flags来确定是否有
//Block_descriptor_2和Block_descriptor_3,
//通过内存偏移获取!
};

block本质上是一个结构体,内部含有isa指针,也为一个oc对象

block分为3种类型

  • _NSConcreteStackBlock 栈区block
  • _NSConcreteGlobalBlock 全局区block
  1. 使用全局变量的时候
  2. 不截获外部变量的时候
  • _NSConcreteMallocBlock 堆区block
  1. 调用block的copy方法的时候
  2. block作为函数返回值返回的时候
  3. 将block赋值给附有_strong修饰符id类型的类或者block类型成员变量时候
  4. 方法中含有usingBlock的Cocoa框架方法或者GCD的API中传递block时候


    image.png

2 循环引用是什么?怎么检测循环引用?怎么解决?怎么出现?

原理:

循环引用指两个(多个)对象之间互相强引用,从而导致这些对象的引用计数始终大于0,无法释放,最后导致内存泄露的现象

检测:

  • 析构方法deinit()
  • Analyze静态分析
    写了一个明显的内存泄漏的代码,结果检测不到
    写了一个没有使用的属性,检测不到
    写了一个没有调用的方法,检测不到
  • Instruments工具中,选择Leaks检测

解决:

delegate跟block,都是用weak修饰即可打破循环
timer循环,在退出页面的时候,手动销毁timer对象即可

复现:

  • delegate
    写了个delegate demo,想复现循环引用的问题,结果把修饰delegate的关键词改成了strong,依旧走了析构方法,意味着,我改成strong之后,没有导致循环引用,暂时找不到原因,有明白的大佬希望指导一下?
    经过大佬点播,本人顿悟,之所以改成strong,还是走了析构,那是因为,第一个VC,压根没有持有第二个VC,所以压根没有循环引用,其他的道理,同以下block

  • block
    写了个block demo,想复现循环引用的问题,还是碰到了问题,我好难,出现循环引用[weak self]解决不了?
    经过大佬的指导,本人顿悟,如果我持有第二个VC,返回上一个VC的时候,第二个VC不会销毁,因为目前当前VC还持有着第二个VC,所以他怎么销毁,如果前面还有一个VC的话,返回前面那个VC,那么后面这两个VC会一并销毁

  • NSTimer
    这个比较简单,但还是有个小插曲:初始化一个timer之后,返回上一个VC,结果走了deinit,定时器却还在走,这既没有造成循环引用,又出乎我的意料之外,在我的印象中,只要走了deinit方法,这个控制器中的对象都应该释放了才对,不然这个控制器怎么会释放
    后面我发现了我的问题:之所以没有造成循环引用,是因为没有互相引用,因为初始化的timer没有创建对象,控制器没有引用到timer的对象,timer的block里边也没有引用控制器,这压根没有引用,哪来的循环,于是我加上之后,完美实现我的循环引用,接着愉快的在viewwilldispear中销毁timer对象,解决了这个循环引用

3 weak,strong,assign,copy的异同?

weak

  • 修饰的对象被释放后,指针自动置为nil,一般解决循环引用

assign

  • 修饰的对象被释放后,指针不会自动置为nil,一般修饰基本数据类型,因为基本数据类型是分配在栈上,系统进行管理,不会造成野指针

strong

  • 使引用计数加1

copy

  • 使引用计数加1,但会新拷贝一个对象,存到另一块内存

相关文章

  • Block汇总

    1 Block的底层原理? //用于描述块对象的>标志 flagsenum {BLOCK_DEALLOCATING...

  • 页面传值方法汇总

    方法汇总 1、属性2、方法3、Delegate代理4、Block回调5、通知6、KVO7、单例8、NSUserDe...

  • block 几乎所有行为的汇总

    概述闭包,可以捕获代码。block对象常量块外的属性 非标准c组成部分。源码部分不粘了 - 主要证明两点 1 是个...

  • iOS开发之Block原理探究

    Block概述 Block本质 Block调用 Block分类 Block循环引用 Block原理探究 Block...

  • block的使用

    定义block 返回类型 (^block名称)(参数) = ^(){block内容}; 调用block block...

  • Block 02 - __block

    Block 02 - __block __block 的作用 __block 可以解决 Block 内部无法修改 ...

  • iOS面试之Block大全

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS面试之Block模块

    Block Block内容如下: 关于Block 截获变量 __block修饰符 Block的内存管理 Block...

  • iOS Block

    Block的分类 Block有三种类型:全局Block,堆区Block,栈区Block 全局Block 当Bloc...

  • iOS block 为什么官方文档建议用 copy 修饰

    一、block 的三种类型block 三种类型:全局 block,堆 block、栈 block。全局 block...

网友评论

      本文标题:Block汇总

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