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
    评论
OC(Objective-C)是一种面向对象的编程语言,它支持在类中使用方法和block。类方法是在类中定义的方法,可以直接通过类名来调用,而不需要实例化对象。而block是一种闭包,可以在代码中定义并传递给方法或函数,用于延迟执行特定的逻辑。 在OC中,可以使用类方法来创建和操作类的实例,例如通过一个工厂方法创建对象,或者在类方法中实现一些与类相关的逻辑。类方法通常使用“+”符号进行声明和实现。 而block可以在方法中作为参数传递,也可以在方法中定义和使用。block可以捕获其所在作用域的变量,可以在方法内部延迟执行一段代码,也可以用于实现回调等功能。block的定义和使用使用“^(){}”语法。 类方法和block可以结合使用,例如可以在类方法中接受一个block作为参数,并在合适的时机调用该block,以实现一些灵活的逻辑。通过类方法和block的组合,可以在OC中实现更加灵活和强大的功能,例如在异步操作中使用block来回调结果,或者在工厂方法中使用block来定制对象的初始化逻辑等。 总而言之,类方法和blockOC中的两个重要特性,它们可以分别用于类的操作和延迟执行逻辑,也可以结合使用以实现更加灵活的功能。在实际的OC开发中,类方法和block通常会被广泛使用,可以帮助开发者更加简洁和灵活地实现代码逻辑。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值