美文网首页
iOS Block 部分二

iOS Block 部分二

作者: 飞不越疯人院 | 来源:发表于2020-06-30 15:53 被阅读0次

主要讲解 Block 的分类和变量捕获的强弱引用;

Block部分一
Block部分二
Block部分三
Block知识点总结

以下内容的测试主要针对ARC环境; MRC下直接贴出测试结果, 不再贴出测试代码, 具体请自行测试MRC环境;

1. 首先是Block的分类

  • NSStackBlock : 访问了auto变量 == 存放在栈区
  • NSMallocBlock : 对__NSStackBlock__进行copy操作 == 存放在堆区
  • NSGlobalBlock : 没有访问auto变量 == 存放在数据区域
    他么的继承关系如图;
总结:

没有访问auto变量,其class__NSGlobalBlock__;
MRC下访问了auto变量, 其class就是__NSStackBlock__然后copy这个block;,其class变为__NSMallocBlock__; 没有访问auto变量,其class__NSGlobalBlock__;
ARC下访问了auto变量, 其class结果是__NSMallocBlock__, 因为系统自动帮忙进行了类似copy的操作将其赋值到堆区;


2. ARC下什么时候会对NSStackBlock进行copy操作?

  • 访问auto变量时;
  • 系统方法中有UsingBlockblock时;
  • 使用GCDblock时;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    ///最简单的block, 没有访问auto变量, 始终都是__NSGlobalBlock__
    NSLog(@"type: %@", [^{} class]);
    ///访问auto局部变量的block;  MRC是__NSStackBlock; ARC下系统copy操作到堆区, 所以就是__NSMallocBlock;
    int a = 10;
    void(^block1)(void) = ^{
        NSLog(@"%d", a);
    };
    NSLog(@"type: %@", [block1 class] );
  
    ///返回值block中没有访问auto局部变量; 始终都是__NSGlobalBlock__
    ReturnBlock block2 = [self getblock1];
    NSLog(@"block作为返回值时, type%@ ", [block2 class]);
  
    ///返回值block中有访问auto局部变量;MRC是__NSStackBlock; ARC下系统copy操作到堆区, 所以就是__NSMallocBlock;
    ReturnBlock block3 = [self getblock2];
    NSLog(@"block作为返回值时, type%@ ", [block3 class]);
    
    ///block被强指针指向, 有访问auto变量, ARC下会默认copy到堆区
    int b = 10;
    ReturnBlock block4 = ^{
        NSLog(@"%d",  b);
    };
    NSLog(@"block被强指针指向 , type%@ ", [block4 class]);

    ///系统方法中有usesblock的字眼的, ARC下会默认copy到堆区
    NSArray *arr = [NSArray array];
    [arr enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        
    }];
    ///使用GCD中, ARC下会默认copy到堆区

}
- (ReturnBlock)getblock1 {
    ReturnBlock block = ^{
        NSLog(@"This is a block");
    };
    return  block;
}
- (ReturnBlock)getblock2 {
    int a = 10;
    ReturnBlock block = ^{
        NSLog(@"This is a block, a = %d", a);
    };
    return  block;
}
@end

3. Block中对象类型的强引用和弱引用?

情形1一个block对实例对象person1强引用:

代码如下;

- (void)test0 {
    TestBlock testblock;
    {
    Person *person1 = [[Person alloc] init];
    testblock =  ^{
            NSLog(@"person1 : %@", person1);
        };
    }
    testblock();
    ///block对person1强引用, 所以即使是出了{}作用域, 仍然可以打印出i其地址, 然后才会dealloc;
}

转换为C++代码后的block实现如下

struct __ViewController2__test0_block_impl_0 {
  struct __block_impl impl;
  struct __ViewController2__test0_block_desc_0* Desc;
  ///对person对象进行了强引用;
  Person *__strong person1;
  __ViewController2__test0_block_impl_0(void *fp, struct __ViewController2__test0_block_desc_0 *desc, Person *__strong _person1, int flags=0) : person1(_person1) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
情形2一个block对实例对象person2弱引用:

代码如下:

- (void)test1 {
    TestBlock testblock;
    {
        Person *person2 = [[Person alloc] init];
        __weak Person *weakPerson2 = person2;
        testblock =  ^{
            NSLog(@"person2 : %@", weakPerson2);
        };
    }
    testblock();
    ///block对weakPerson2弱引用,出了{}作用域后person2即销毁, 直接打印dealloc, 然后调用block时打印出的地址为null;
}

转换为C++代码后的block实现如下

struct __ViewController2__test1_block_impl_0 {
  struct __block_impl impl;
  struct __ViewController2__test1_block_desc_0* Desc;
///对weakPerson2进行了弱引用
  Person *__weak weakPerson2;
  __ViewController2__test1_block_impl_0(void *fp, struct __ViewController2__test1_block_desc_0 *desc, Person *__weak _weakPerson2, int flags=0) : weakPerson2(_weakPerson2) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};

通过指令将OC文件转换为C++文件
指令: xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 文件.m -o 文件-arm64.cpp


参考文章和下载链接
测试代码
iOS clang指令报错问题总结
Apple 一些源码的下载地址
auto修饰符
C++中结构体的构造函数
全局变量、静态全局变量、静态局部变量和普通局部变量的区别

相关文章

  • iOS Block 部分二

    主要讲解 Block 的分类和变量捕获的强弱引用; Block部分一Block部分二Block部分三Block知识...

  • iOS 题目详解 部分三

    主要讲解Block 内部使用strongSelf的理由和用法 iOS 题目详解 部分一iOS 题目详解 部分二...

  • block系列文章总结

    iOS源码解析:Block的本质<一>iOS源码解析:Block的本质<二>Objective C block背后...

  • iOS Block 部分一

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

  • iOS Block 部分三

    主要讲解 Block内修改外部变量, 内存管理, 以及循环引用; Block部分一Block部分二Block部分三...

  • OC--Block总结

    参考 Block编译代码解读:block没那么难(一、二、三)iOS进阶——iOS(Objective-C) 内存...

  • Block - block简单的使用

    参考文档 iOS Block详解 一、忘记block格式? 样例一.png 样例二.png 二、Block的定义 ...

  • iOS-2 Block

    block块 系列文章: iOS Block浅浅析 - 简书 iOS Block实现原理 iOS Block __...

  • Block

    xx_cc iOS底层原理总结 - 探寻block的本质(一)iOS底层原理总结 - 探寻block的本质(二) ...

  • iOS Block存储域及循环引用

    系列文章:iOS Block概念、语法及基本使用iOS Block实现原理iOS Block __block说明符...

网友评论

      本文标题:iOS Block 部分二

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