• iOS打基础之Block二三事


    Block概念

    Objective-C中的Block本质是一个对象。 也可以把block理解为闭包。

    Block的创建和使用

    void (^block变量名)(NSString* 参数1...);
    block变量名 = ^(NSString* 参数1...){
    	函数体
    };
    block变量名();
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在GCD中给我们提供了一个无返回值,无参数的block定义。

    @property (nonatomic, copy) dispatch_block_t block;
    
    • 1

    在这里插入图片描述

    Block的实现

    struct Block_descriptor {
        unsigned long int reserved;
        unsigned long int size;
        void (*copy)(void *dst, void *src);
        void (*dispose)(void *);
    };
    
    struct Block_layout {
        void *isa;
        int flags;
        int reserved;
        void (*invoke)(void *, ...);
        struct Block_descriptor *descriptor;
        /* Imported variables. */
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    分析

    • isa指针,代表着Block本身也是被当做一个对象进行处理的。
      • 这样设计有什么好处吗?
      • 还可以怎样设计吗?
    • flags 用于按bit位表示一些block附加信息。
      • 怎么使用flags
      • 为什么要设计bits
    • reserved 保留变量
      • 怎样使用保留变量?
    • invoke 函数指针,指向block实现的函数调用地址。
      • 指向的函数是什么样子的?
    • descriptor 表示该block的附加描述信息。
      • size,大学
      • copy 拷贝函数
      • dispose 释放函数
    • variables 捕获的变量

    Block分类

    NSConcreteGlobalBlock

    不捕获变量。

    NSConcreteStackBlock

    分配到占上的实例。

    思考

    • 既然Block是一个对象,为什么会被分配到栈上?为什么要把他分配到栈上?这样设计有什么好处?

    NSConcreteMallocBlock

    堆Block,通常不会在源码中出现。默认当一个block在被copy时,才会将block复制到堆上。

    Block变量捕获

    • 对于Block外变量的引用,block默认将其复制到数据结构中实现访问。
    • 对于__block修饰的外部变量引用,block是将其复制到其引用地址实现访问的。

    __block 原理

    struct __Block_byref_i_0 {
        void *__isa;
        __Block_byref_i_0 *__forwarding;
        int __flags;
        int __size;
        int i;
    };
    
    struct __main_block_impl_0 {
        struct __block_impl impl;
        struct __main_block_desc_0* Desc;
        __Block_byref_i_0 *i; // by ref
        __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) {
            impl.isa = &_NSConcreteStackBlock;
            impl.Flags = flags;
            impl.FuncPtr = fp;
            Desc = desc;
        }
    };
    static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
        __Block_byref_i_0 *i = __cself->i; // bound by ref
    
        printf("%d\n", (i->__forwarding->i));
        (i->__forwarding->i) = 1023;
    }
    ...
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 使用__block后,捕获的变量以一个__Block_byref_i_0的形式存在,同时在__main_block_func_0中使用的事__Block_byref_i_0的结构体指针,保证改变的是外部的变量的值。
    • __Block_byref_i_0结构体中保存的是捕获的外部变量的地址,forwarding的作用是在拷贝到堆上后,保证指针指向的是堆上的地址。

    Objective-C 中的block

    ARC模式下,将只有全局block堆block

    Block的使用场景

    • GCD 使用block做任务回调。
    • 使用Block进行通信。

    Swift的闭包

    • 待补充…

    参考文章

    [1] https://blog.devtang.com/2013/07/28/a-look-inside-blocks/

  • 相关阅读:
    撸了一个 Feign 增强包 V2.0 升级版
    安卓常见设计模式4------原型模式(Kotlin版)
    Mac 安装 nvm 教程
    【JavaEE】初识计算机网络(TCP/IP五层模型及封装和分用)
    【RocketMQ】【源码】Dledger日志复制源码分析
    一个简单的HTML网页 、个人主页网页设计(HTML+CSS)
    【JAVA入门】JUnit单元测试、类加载器、反射、注解
    【Python爬虫必备技术栈】urllib库&&urllib3库
    C++的struct和class的区别
    感谢有你 | FISCO BCOS 2022年第二季度贡献榜单
  • 原文地址:https://blog.csdn.net/Ambrosedream/article/details/126018486