美文网首页
block的理解

block的理解

作者: T_guo | 来源:发表于2019-10-24 16:01 被阅读0次

    1..block的原理是什么?本质是什么?

    block本质上也是一个OC对象,它内部也有个isa指针,block是封装了函数调用以及函数调用环境的的OC对象。
    blockl底层是一个结构体,里面有__block_impl结构体,和__main_block_desc_0指针,_block_impl结构体里有isa指针,FuncPtr指针,FuncPtr将来指向要执行的代码的地址;__main_block_desc_0指针描述block的大小等,

    2.block的类型?

    有三种类型,可以通过调用class方法或者isa指针查看具体类型,最终都是继承自NSBlock类型
    NSGlobalBlock_ 放在数据区
    NSStackBlock_ 放在栈区 栈:系统会自动分配内存,不需要程序员手动管理
    NSMallocBlock_ 放在堆区 堆:动态分配内存,需要程序员手动申请,也需要程序员自己管理内存
    不管是全局还是局部,只要没有访问auto变量就为NSGlobalBlock类型。
    在MRC下,访问auto变量就为NSStackBlock
    类型,NSStackBlock类型是存放在栈区,内存会出现问题,内存会自动销毁,因此要想方法放在堆区,只需要我们在NSStackBlock类型调用copy就会升级成为NSMallocBlock类型
    NSGlobalBlock
    类型调用copy什么也不做,还是在NSGlobalBlock类型,在数据区
    NSMallocBlock
    类型调用copy,还是在NSMallocBlock_类型,只是引用计数器增加

    3._block的作用是什么?有什么使用注意点?

    block不能修改外部的值,因为block底层里面,所修改的变量都不在同一个函数,当所修改变量所在的函数执行完后都释放了,在另一个函数里是不能修改的。
    当变量用static修饰时,block内部就可以修改变量的值,因为static修饰的局部变量在block内部是地址传递,这个变量在block内部是指针,这个指针存储的地址值是外面变量的地址。一般不用static修改变量的值,因为static会改变变量的性质,是变量永久在内存中
    __block修饰, block内部就也可以修改变量的值,而且__block不改变变量的性质(变量还是auto)。
    总结:
    __block可以用于解决block内部无法修改auto变量值的问题
    __block不能修饰全局变量,静态变量(static)
    编译器会将__block变量包装成一个对象(这个对象底层是一个结构体)

    4.__block的内存管理?

    当block在栈上时,并不会对__block变量产生强应用
    当block被拷贝到堆上时,
    会调用block内部的copy函数
    copy函数内部会调用_Block_object_assign函数
    _Block_object_assign函数会对__block变量形成强引用(retain)
    当block从堆上移除
    会调用block内部的dispose函数
    dispose函数内部会调用_block_object_dispose函数
    _block_object_dispose函数会自动释放引用的auto变量,类似于release
    被__block修饰的对象类型:
    当block在栈上时,并不会对指向的对象产生强应用
    当_block变量被copy到堆时
    会调用block内部的copy函数
    copy函数内部会调用_Block_object_assign函数
    _Block_object_assign函数会根据所指向对象的修饰符变量做出响应的操作,形成强应用或者若引用(注意:这里仅限于ARC时会retain,MRC时不会retain)
    当block从堆上移除
    会调用block内部的dispose函数
    dispose函数内部会调用_block_object_dispose函数
    _block_object_dispose函数指向的对象,类似于release
    ARC循环引用解决:
    __weak:弱引用(首选方案)不会产生强引用,指向的对象销毁时,会自动让指针置为nil
    __unsafe_unretain:弱引用,不安全 ,指向的对象销毁时,指针存储的地址值不变
    __block:缺点就是必须执行block,清空指针
    MRC循环引用解决:
    不支持__weak的
    __unsafe_unretain
    __block

    5.block的属性修饰为什么是copy?使用block有哪些使用注意?

    block一旦不copy它就在栈上或者全局区,不会在堆上。在堆上方便我们进行能存管理
    循环引用

    注意:

    对于一个不是static修饰的局部变量先赋值,再block里面使用,block外部再重新复制后,block里面的值不改变,因为当初创建block对象的时候,局部变量的值已经存储到了block里面(变量的值已经捕获到block里面了)
    如果是static修饰的局部变量,再block里面使用,block外部再重新复制后,block里面的值会改变,因为static修饰的局部变量在block内部是地址传递
    只要是局部变量block都将会捕获局部变量的值,因为作用域的问题。
    auto(自动变量):离开作用域就会自动销毁,只存在于局部变量,访问方式是值传递
    static(静态局部变量):访问方式是地址传递
    不管是auto全局变量还是static全局变量,block都不会捕获它们的值。因为是全局变量,在哪里都可以访问因此不需要捕获,可以直接访问。

    相关文章

      网友评论

          本文标题:block的理解

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