Block(块)

作者: Ryker_Bay | 来源:发表于2016-09-25 15:25 被阅读213次

    定义

    带有局部变量(自动变量)的匿名函数

    ps :
    “带有局部变量”:可以获取到块外面的变量(将变量放在自身(block)的结构体中;获取的只是改变量的瞬时值,后面对变量的修改不会使块中的变量也被修改),但是只能读取;
    要改写的话需给变量前面加"__block"修饰符 _(将该变量变成和Block一样的结构体实例,并在自身的结构体添加一个对结构体中值的指针引用;分开两个结构体(block的结构体 , 变量的结构体)是为了能够在多个Block中用到_block变量)

    本质

    C语言中的结构体和函数,OC语言中对象

    语法

    ^ 返回值类型 参数列表 表达式(斜体代表可省略)

    ps:
    省略返回值类型时,如果表达式中有return就使用该返回值的类型,如果没有return就使用void类型;表达式中含多个return语句时,所有return的返回值类型必须一致

    分类

    所属类 说明
    栈块 _NSConcreteStackBlock 编译器会给每个块分配好栈内存, 然而等离开了相应的范围之后,编译器有可能把分配给块的内存覆写掉。
    堆块 _NSConcreteMallocBlock 带引用计数的块对象;栈块通过copy方法可成为堆块
    全局块 _NSConcreteGlobalBlock (存储域为程序的数据区域 .data区) 块不会捕捉任何状态(比如外围的变量等),运行时也无须有状态来参与。块所使用的整个内存区域,在编译期已经完全确定了。

    ps:全局块:对其的拷贝操作是个空操作,因为全局块决不可能为系统所目收。这种块实际上相当于单例。下面就是个全局块:

    void (^ablock)() = ^{
        NSLog(@"This is a block");
    
    }
    

    由于运行该块所需的全部信息都能在编译期确定,所以可把它做成全局块。这完全是种优化技术:若把如此简单的块当成复杂的块来处理,那就会在复制及丢弃该块时执行

    9460be12gw1eyxyexv5omj20zi0t6tdm.jpg

    )

    从栈到堆

    对于Block (用copy方法)

    使用场景:向方法或函数的参数中传递Block时
    不需手动复制的情况:

    • Cocoa框架的方法且方法名中含有usingBlock时
      
    • GCD的API
      
    • 将block作为函数返回值返回时,将Block赋值给用__strong修饰的id类或Block类型成员变量时,编译器会自动将对象的Block作为参数并调用_Block_copy函数(和copy效果一样)
      
    源存储域 复制效果
    栈 -> 堆
    引用计数增加
    程序的数据区域 什么也不做

    对于__block变量

    跟随Block移动:当一个引用__block变量的Block从栈到堆时,__block变量也从栈到堆,并持有该变量;当有另外一个也引用了该__block变量的Block从栈到堆时,该Block也持有该变量并且该变量引用计数加一,

    参考资料:
    《Objective-C高级编程》

    相关文章

      网友评论

      本文标题:Block(块)

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