美文网首页
Block 01 - 底层实现

Block 01 - 底层实现

作者: 石头89 | 来源:发表于2019-08-05 16:18 被阅读0次

Block 01 - 底层实现

Block 是一个封装了函数调用以及函数调用环境的 Objective-C 对象。
使用 Block 可以实现闭包,它是对 C 语言的一种扩充功能,我们的代码块在底层被封装成了一个函数,函数指针是 Block 底层结构体的一个成员,Block 底层有对外部局部变量捕获的机制。

Block 的底层实现

// Block 底层实现的基础结构体
struct __block_impl {
    void *isa;    // Block Class 对象的指针
    int Flags;    // 标志变量,在实现 Block 的内部操作时会用到
    int Reserved; // 保留字段
    var *FuncPrt; // 功能函数的指针
};

// Block 的底层实现,Block 本质是一个 Objective-C 对象
//
// 当 Block 在栈上时,不会对 auto 变量指向的对象、__block 对象进行强引用。
struct __xxx_block_impl_0 {
    struct __block_impl impl;        // 底层实现的基础结构体
    struct __xxx_block_desc_0 *Desc; // Block 的描述信息
    // auto_ivars...         // 被捕获的局部 auto 变量
    // *block_byref_ivars... // 被捕获的局部 auto 变量(__block 对象)
    // *static_ivars...      // 被捕获的局部 static 变量
    // 全局变量不需要捕获,在功能函数中直接访问

    // Constructor
    //
    // *fp: 功能函数的指针
    // *desc:当前结构体占用内存的大小
    // _auto_vars: 外部的局部 auto 变量(值传递)
    // *_block_byref_ivars: 外部的局部 auto 变量(__block 对象,引用传递)
    // *_static_vars: 外部的局部 static 变量(引用传递)
    __xxx_block_impl_0(void *fp, struct __xxx_block_desc_0 *desc, 
                       _auto_vars..., *_block_byref_ivars..., *_static_vars..., 
                       int flags = 0) : 
                       auto_ivar0(_auto_var0)..., 
                       block_byref_ivar0(_block_byref_ivar0)...,
                       static_ivar0(_static_var0)... {
        // _NSConcreteGlobalBlock _NSConcreteStackBlock _NSConcreteMallocBlock   
        impl.isa = &_NSConcreteStackBlock; 
        impl.Flags = flags;
        impl.FuncPrt = fp;
        Desc = desc;
    }
};

// Block 的描述信息
static struct __xxx_block_desc_0 {
    size_t reserved;   // 保留字段
    size_t Block_size; // Block 占用内存的大小
    void (*copy)(struct __xxx_block_impl_0*, struct __xxx_block_impl_0*); // 为 auto 变量指向的对象、__block 对象做内存管理
    void (*dispose)(struct __xxx_block_impl_0*); // 为 auto 变量指向的对象、__block 对象做内存管理
} __xxx_block_desc_0_DATA = { 0, sizeof(struct __xxx_block_impl_0), 
                              __xxx_block_copy_0, __xxx_block_dispose_0 };

// 当 Block 被拷贝到堆上时:
// 会调用 Block 内部的 copy 函数。
// copy 函数内部会调用 _Block_object_assign 函数。
// _Block_object_assign 函数会对 __block 对象进行强引用。
// _Block_object_assign 函数会根据 auto 变量的修饰符(__strong, __weak, __unsafe_unretained)做出相应的操作,进行强引用(retain)或弱引用。                             
static void __xxx_block_copy0(struct __xxx_block_impl_0 *dst, 
                              struct __xxx_block_impl_0 *src) {
    _Block_object_assign((void*)&dst->auto_ivar0, (void*)src->auto_ivar0, 3/*BLOCK_FIELD_IS_OBJECT*/);
    _Block_object_assign((void*)&dst->block_byref_ivar0, (void*)src->block_byref_ivar0, 8/*BLOCK_FIELD_IS_BYREF*/);
}

// 当 Block 从堆上移除时:
// 会调用 Block 内部的 dispose 函数。
// dispose 函数内部会调用 _Block_object_dispose 函数。
// _Block_object_dispose 函数会自动释放被强引用的对象(release)。
static void __xxx_block_dispose(struct __xxx_block_impl_0 *src) {    
    _Block_object_dispose((void*)src->auto_ivar0, 3/*BLOCK_FIELD_IS_OBJECT*/);
    _Block_object_dispose((void*)src->block_byref_ivar0, 8/*BLOCK_FIELD_IS_BYREF*/);
}

// 功能函数的底层实现
static void __xxx_block_func_0(struct __xxx_block_impl_0 *__cself, vars...) {
    // auto_ivar0 = __cself->auto_ivar0;                // bound by copy
    // *block_byref_ivar0 = __cself->block_byref_ivar0; // bound by ref
    // *static_ivar0 = __cself->static_ivar0;           // bound by copy
    // ...
    
    // do something...
}

Block 的底层原理

Block 是一个封装了函数调用以及函数调用环境的 Objective-C 对象。

  • Block 底层通过结构体实现,内部也有一个 isa 指针。
  • Block 内部通过一个指针调用功能函数。
  • Block 会对外部局部变量进行捕获。

Block 底层结构图

Block 的变量捕获(Capture)

为了保证 Block 内部能够正常访问外部的局部变量,Block 有变量捕获机制。


auto 变量的捕获示意图:


Block 的类型

Block 有 3 种类型,可以通过 class 方法或 isa 指针查看具体类型,3 种类型都是 NSBlock 的子类。

  • NSGlobalBlock (_NSConcreteGlobalBlock)
    • NSGlobalBlock --> __NSGlobalBlock --> NSBlock --> NSObject
  • NSStackBlock (_NSConcreteStackBlock)
    • NSStackBlock --> __NSStackBlock --> NSBlock --> NSObject
  • NSMallocBlock (_NSConcreteMallocBlock)
    • NSMallocBlock --> __NSMallocBlock --> NSBlock --> NSObject

括号前面的是运行时的 Block 类型,括号内是将 Objective-C 转换为 C++ 后的类型。
Blocks 都派生自 NSBlock,NSBlock 的父类是 NSObject。

Block 所在的内存区域

Block 调用 copy 后的结果

Block 的使用示例

定义完 Block 直接调用:

int sum = ^(int a, int b) {
    return a + b;
}(1, 2);

先定义 Block 再调用:

int (^add)(int, int) = ^(int a, int b) {
    return a + b;
};
int sum = add(1, 2);

函数接收一个 Block,函数内部调用 Block:

void fetchData(void (^completion)(id result)) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^ {
        // do something..
        completion(@"hello~");
    });
}

fetchData(^(id result) {
    NSLog(@"result: %@", result);
});

与上面示例的不同之处在于为 Block 先定义一个类型:

typedef void (^Completion)(id result);

void fetchData(Completion completion) {
    dispatch_async(dispatch_get_global_queue(0, 0), ^ {
        // do something...
        completion(@"hello~");
    });
}

fetchData(^(id result) {
    NSLog(@"result: %@", result);
});

将 Block 作为属性使用:

@interface Player : NSObject
@property (nonatomic, copy) void (^onStop)(void);
- (void)stop;
@end

@implementation Player
- (void)stop {
    self.onStop();
}
@end

Player *player = [[Player alloc] init];
player.onStop = ^ {
    NSLog(@"停止播放");
};
[player stop];

相关文章

  • Block 01 - 底层实现

    Block 01 - 底层实现 Block 是一个封装了函数调用以及函数调用环境的 Objective-C 对象。...

  • Today面试

    Runloop 底层原理Kvo 底层原理ARC 底层原理 如何实现GCD 底层原理Block 底层原理Aut...

  • iOS Block 部分一

    主要讲解 Block 的底层实现原理; Block部分一Block部分二Block部分三Block知识点总结 基础...

  • block底层实现

    最近读书,关于block的底层实现,有以下思考和总结 c++部分的相关步骤分析写在代码注释 一、block是什么 ...

  • Block底层实现

    《objective-c高级编程》这本书是一本非常好的书,但是时间比较早,书中有一些理论不适合最新的ios版本,并...

  • iOS底层原理 - 窥探Block的本质(一)

    通过窥探Block的底层实现,解答以下问题 1.Block底层数据结构是什么,本质是什么2.Block与其所访问的...

  • block 本质

    一.block底层源码实现 1.定义一个简单的block 2.生成对应的底层代码: xcrun -sdk ipho...

  • 100篇技术文章

    1.Class类的底层实现原理 - 链接 链接 2.Category分类的底层实现原理 - 链接 3.Block块...

  • Block是如何实现的?Block的数据结构是什么?__bloc

    block本质是一个对象,底层用struct实现。数据结构如下:struct Block_descriptor {...

  • iOS开发——block底层实现与变量捕获

    前言 首发地址:block底层实现与变量捕获 带着问题阅读 block的本质是什么?你能讲出来它的底层结构吗? 全...

网友评论

      本文标题:Block 01 - 底层实现

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