OC block底层实现原理

先看两个实例

1、

typedef void(^captureObjectBlock)(void);
captureObjectBlock testBlock;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self captureObject];
    testBlock();
}

- (void)captureObject {
    int captureNum = 1;
    testBlock = ^() {
        NSLog(@"num = %d", captureNum);
    };
    captureNum = 2;
}

上面打印的是几?captureNum 出作用域之后是否别销毁?
打印结果:

num = 1

同样类型的实例

typedef void(^captureObjectBlock2)(NSObject *);
captureObjectBlock2 testBlock2;

- (void)viewDidLoad {
    [super viewDidLoad];
    [self captureObject2];
    testBlock2([[NSObject alloc] init]);
    testBlock2([[NSObject alloc] init]);
    testBlock2([[NSObject alloc] init]);
}

- (void)captureObject2 {
    NSMutableArray *mutArray = [[NSMutableArray alloc] init];
    testBlock2 = ^(NSObject *obj) {
        [mutArray addObject:obj];
        NSLog(@"mutArray元素的个数:%ld", [mutArray count]);
    };
}

打印的数组的个数是多少?
有人会回答:mutArray是captureObject方法的局部变量,mutArray指针 保存到栈上,那么当执行完captureObject方法后,出去了作用域mutArray变量就会被系统自动释放。

所以当执行captureBlk([[NSObject alloc] init]); 的时候,mutArray为nil,每次打印的为0。

这是错误的,实际为

mutArray元素的个数:1
mutArray元素的个数:2
mutArray元素的个数:3

那么如果把上面代码中的mutArray改为weak类型:

NSMutableArray __weak *mutArray = [[NSMutableArray alloc] init];

打印结果:

mutArray元素的个数:0
mutArray元素的个数:0
mutArray元素的个数:0

2、

    __block int testNum = 10;
    void (^block)(void) = ^() {
        NSLog(@"读取局部变量:%d", testNum);
        testNum = 1000;
    };
    testNum = 20;
    block();
    NSLog(@"block执行后的值:%d", testNum);

打印结果:

读取局部变量:20
block执行后的值:1000

本文会分析上面的代码中block底层 都做了哪些操作。

用过block的可以 直接忽略前面的语法部分。直接从第三部分看即可。

一、block的使用

1、block声明

void (^blockName)(int arg1, int arg2);

中文翻译:返回值(^block变量名)(block的参数)
参数名称可以省略,也可以写成:

void (^blockName)(int, int);

2、block定义

^void(int arg1, int arg2) {
};

中文翻译:^返回类型(block的参数)
返回类型可以省略,也可以写成:

^(int arg1, int arg2) {};

声明定义和调用:

    void (^blockName)(int, int) = ^(int arg1, int arg2) {
        NSLog(@"arg1 + arg2 = %d", arg1 + arg2);
    };
    blockName(1,2);

block作为方法的参数:

- (void)viewDidLoad {
    //2、没有参数
    void (^blockName2)() = ^() {
        NSLog(@"block2");
    };
    blockName2();

    //3、block有返回值
    int (^blockName3)(int) = ^(int n) {
        return n * 2;
    };
    //4、block作为方法的参数
    [self testBlock2:blockName3];
}

- (void)testBlock2:(int(^)(int))myBlock {
    myBlock(10);
}

3、block只有在调用的时候才会执行里面的函数内容。

二、block调用外部变量

1、全局变量,block可以进行读取和修改。

@interface ViewController () {
   
    NSInteger num;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值