iOS Block底层解析二

2020-04-13  本文已影响0人  KOLee

一、__block 的解析

void test8(int a) {
    a++;
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        int b = 10;
        test8(b);
        NSLog(@"%d",b);      
    }
    return 0;
}
打印结果: 
2020-04-13 21:12:24.922403+0800 blockTest[3434:163752] 10
 // 对象类型
void test6() {
    Person *p = [Person new];
    p.name = @"hello block!";
    void(^block)(void) = ^{
        p.name = @"fuck block!";
        NSLog(@"--- %@",p.name);
    };
    block();
}
打印结果:
2020-04-13 21:18:06.198269+0800 blockTest[3486:167284] --- fuck block!

void test8() {
    NSMutableArray * arr = [NSMutableArray new];
    void(^block)(void) = ^{
        [arr addObject:@2];
        NSLog(@"--- %@",arr);
    };
    block();
}
打印结果:
2020-04-13 21:25:44.568467+0800 blockTest[3515:170553] --- (
    2
)
// __block作用
void test7() {
    
    __block int age = 10;
    __block NSObject *objc = [[NSObject alloc] init];
    void(^block)(void) = ^ {
        objc = nil;
        age = 20;
    };
    block();
}
把转换的去掉简化代码,摆好步骤:
// 第一步
int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        test7();
    }
    return 0;
}

// 第二步
void test7() {
    // __block int age = 10;
    __Block_byref_age_0 age = {
        0,
        &age,
        0,
        sizeof(__Block_byref_age_0),
        10
        
    };
    //    __block NSObject *objc = [[NSObject alloc] init];
    __Block_byref_objc_1 objc = {
        0,
        &objc,
        33554432,
        sizeof(__Block_byref_objc_1),
        __Block_byref_id_object_copy_131,
        __Block_byref_id_object_dispose_131,
        objc_msgSend((id)(objc_msgSend(objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"))
     };
    
    // 调用
    void(*block)(void) = &__test7_block_impl_0(__test7_block_func_0, &__test7_block_desc_0_DATA, (__Block_byref_objc_1 *)&objc, (__Block_byref_age_0 *)&age, 570425344));
    block->FuncPtr(block);
}

// 第三步
struct __Block_byref_age_0 {
  void *__isa; // isa指针
__Block_byref_age_0 *__forwarding; // 指向自己的指针
 int __flags; // 不清楚是什么鬼 猜测是标识符什么的
 int __size; // 当前结构体的大小
 int age; // 捕获值
};

// 第三步
struct __Block_byref_objc_1 {
  void *__isa; // isa指针
__Block_byref_objc_1 *__forwarding; // 指向自己的指针
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);  // 执行copy操作
 void (*__Block_byref_id_object_dispose)(void*); // 执行dispose操作
 NSObject *objc;// 捕获 NSObject类型指针
};

// 第四步
static void __test7_block_func_0(struct __test7_block_impl_0 *__cself) {

    // 拿到 __Block_byref_objc_1里面 *objc指针
  __Block_byref_objc_1 *objc = __cself->objc; // bound by ref
    // 拿到__Block_byref_age_0里面 *age指针
  __Block_byref_age_0 *age = __cself->age; // bound by ref
        //objc->__forwarding指针指向 __Block_byref_objc_1 拿到里面的的objc 完成赋值
        (objc->__forwarding->objc) = __null;
        //age->__forwarding指针指向 __Block_byref_age_0 拿到里面的的age 完成赋值
        (age->__forwarding->age) = 20;
}

// 第五步
struct __test7_block_impl_0 {
  struct __block_impl impl;
  struct __test7_block_desc_0* Desc;
  __Block_byref_objc_1 *objc; //__Block_byref_objc_1 类型结果体
  __Block_byref_age_0 *age; //__Block_byref_age_0类型结果体
  __test7_block_impl_0(void *fp, struct __test7_block_desc_0 *desc, __Block_byref_objc_1 *_objc, __Block_byref_age_0 *_age, int flags=0) : objc(_objc->__forwarding), age(_age->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

1.第一步一样,第二步多了两个东西,其实是一个鬼东西,差不多 __Block_byref_age_0和__Block_byref_objc_1两个结构体
2.第三就是对这两个结构体的解析,是不是就是一个类,包装成类,然后再保存在block结构体里面
3.第四步就是赋值个过程了__forwarding指针为啥要这样搞,明明已经拿到*objc的指针了,又(objc->__forwarding->objc) 这样拿objc,这他么不是吓搞吗?我们想一下,前面说的内存管理,很多时候block会copy到堆上的,然后苹果是这样设计的 如图:


图片.png
图片.png
这样搞的好处就是:

二、__weak 修饰、 __strong修饰、block的循环引用问题

  1. 两个是否相互强引用 2.两个以上是否形成强引用闭环
  1. 两个是否相互强引用 2.两个以上是否形成强引用闭环
一个人的精力有限,对你的思念无限
上一篇 下一篇

猜你喜欢

热点阅读