oc——block

block概述

oc类是对数据和相关行为的封装,block是单一任务或行为的封装
  • block属于oc对象,因此block可被添加到容器中
  • block可捕获外围作用域对象,这类似于其他语言的闭包或lambda

block语法

可定义block类型对象及使用block字面值
void block()
{
    void (^feed0)(void) = ^ void (void)
    {
        NSLog(@"feed nothing");
    };
    
    void (^feed1)(int) = ^ void (int rice)
    {
        NSLog(@"feed rice");
    };
    
    void (^feed2)(int, int) = ^ void (int rice, int meat)
    {
        NSLog(@"feed rice and meat");
    };
    
    feed0();
    feed1(5);
    feed2(5, 8);
}
注意:
  • 左边为block对象定义,block类型形似函数指针类型
  • 右边为block字面值,形似函数对象定义(缺少函数名)
  • block字面值返回值类型可从block字面值中推导出来,因此可omit
  • block字面值若无参,参数类型说明可omit
  • block对象若为nil,调用会导致crash,这与oc实例对象不同,oc实例对象为nil,调用不会crash
因此下面代码与上面代码等价
void block()
{
    void (^feed0)(void) = ^
    {
        NSLog(@"feed nothing");
    };
    
    void (^feed1)(int) = ^ (int rice)
    {
        NSLog(@"feed rice");
    };
    
    void (^feed2)(int, int) = ^ (int rice, int meat)
    {
        NSLog(@"feed rice and meat");
    };
    
    feed0();
    feed1(5);
    feed2(5, 8);
}
函数指针类型可typedef,block类型也可typedef
typedef void (^Feed0)(void);
typedef void (^Feed1)(int);
typedef void (^Feed2)(int, int);

void block()
{
    Feed0 feed0 = ^
    {
        NSLog(@"feed nothing");
    };
    
    Feed1 feed1 = ^ (int rice)
    {
        NSLog(@"feed rice");
    };
    
    Feed2 feed2 = ^ (int rice, int meat)
    {
        NSLog(@"feed rice and meat");
    };
    
    feed0();
    feed1(5);
    feed2(5, 8);
}
函数指针类型可作为函数或方法参数,block类型也可作为函数或方法参数
typedef void (^Feed0)(void);
typedef void (^Feed1)(int);
typedef void (^Feed2)(int, int);

void blockArg1(Feed0 feed0)
{
    feed0();
}

void blockArg2(Feed1 feed1, Feed2 feed2)
{
    feed1(5);
    feed2(5, 8);
}

void block()
{
    blockArg1(^
              {
                  NSLog(@"feed nothing");
              });
    
    blockArg2(^ (int rice)
             {
                 NSLog(@"feed rice");
             },
             ^ (int rice, int meat)
             {
                 NSLog(@"feed rice and meat");
             });
}

@interface FBAnimal : NSObject

- (void)blockArg1: (Feed0)feed0;
- (void)blockArg2: (Feed1)feed1 andFeed2: (Feed2)feed2;

- (void)block;

@end

@implementation FBAnimal

- (void)blockArg1: (Feed0)feed0
{
    feed0();
}

- (void)blockArg2: (Feed1)feed1 andFeed2: (Feed2)feed2
{
    feed1(5);
    feed2(5, 8);
}

- (void)block
{
    [self blockArg1:^
    {
        NSLog(@"feed nothing");
    }];
    
    [self blockArg2:^ (int rice)
    {
        NSLog(@"feed rice");
    } andFeed2:^ (int rice, int meat)
    {
        NSLog(@"feed rice and meat");
    }];
}

@end
注意:尽管函数或方法并没有限制block类型参数个数,但在实践中,建议至多使用一个block类型参数,如果函数或方法包含多个参数,出于代码可读性考虑,建议把block类型参数放在最后,这样直接使用block字面值传递实参值,代码可读性会好很多

capture value

无__block


@interface FBAnimal : NSObject

@end

@implementation FBAnimal

@end

void block()
{
    int food = 5;
    int* pFood = &food;
    FBAnimal *animal = [[FBAnimal alloc] init];
    
    NSLog(@"start: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
    NSLog(@"start: food = %d, pFood = %p, animal = %p", food, pFood, animal);
    
    void (^captureBlock)(void) = ^
    {
        NSLog(@"block start: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
        NSLog(@"block start: food = %d, pFood = %p, animal = %p", food, pFood, animal);
        
        //food = 15;
        //pFood = NULL;
        //animal = [[FBAnimal alloc] init];
        
        NSLog(@"block end: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
        NSLog(@"block end: food = %d, pFood = %p, animal = %p", food, pFood, animal);
        
    };
    
    food = 25;
    pFood = NULL;
    animal = [[FBAnimal alloc] init];
    
    NSLog(@"end: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
    NSLog(@"end: food = %d, pFood = %p, animal = %p", food, pFood, animal);
    
    captureBlock();
}

output:
start: food addr = 0x7fff50aab96c, pFood addr = 0x7fff50aab960, animal addr = 0x7fff50aab958
start: food = 5, pFood = 0x7fff50aab96c, animal = 0x7f84734aa180
end: food addr = 0x7fff50aab96c, pFood addr = 0x7fff50aab960, animal addr = 0x7fff50aab958
end: food = 25, pFood = 0x0, animal = 0x7f84734ab140
block start: food addr = 0x7f8473412c30, pFood addr = 0x7f8473412c28, animal addr = 0x7f8473412c20
block start: food = 5, pFood = 0x7fff50aab96c, animal = 0x7f84734aa180
block end: food addr = 0x7f8473412c30, pFood addr = 0x7f8473412c28, animal addr = 0x7f8473412c20
block end: food = 5, pFood = 0x7fff50aab96c, animal = 0x7f84734aa180












结论:
  • 定义block时,block内capture对象copy了block外对象,并非同一对象,且block内对象不可修改
含__block


@interface FBAnimal : NSObject

@end

@implementation FBAnimal

@end

void block()
{
    __block int food = 5;
    __block int* pFood = &food;
    __block FBAnimal *animal = [[FBAnimal alloc] init];
    
    NSLog(@"start: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
    NSLog(@"start: food = %d, pFood = %p, animal = %p", food, pFood, animal);
    
    void (^captureBlock)(void) = ^
    {
        NSLog(@"block start: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
        NSLog(@"block start: food = %d, pFood = %p, animal = %p", food, pFood, animal);
        
        food = 15;
        pFood = NULL;
        animal = [[FBAnimal alloc] init];
        
        NSLog(@"block end: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
        NSLog(@"block end: food = %d, pFood = %p, animal = %p", food, pFood, animal);
        
    };
    
    food = 25;
    pFood = NULL;
    animal = [[FBAnimal alloc] init];
    
    NSLog(@"end: food addr = %p, pFood addr = %p, animal addr = %p", &food, &pFood, &animal);
    NSLog(@"end: food = %d, pFood = %p, animal = %p", food, pFood, animal);
    
    captureBlock();
}

output:

start: food addr = 0x7fff53a37950, pFood addr = 0x7fff53a37930, animal addr = 0x7fff53a37910
start: food = 5, pFood = 0x7fff53a37950, animal = 0x7f83aadbe270
end: food addr = 0x7f83aadc1c58, pFood addr = 0x7f83aadba148, animal addr = 0x7f83aadc4768
end: food = 25, pFood = 0x0, animal = 0x7f83aadba150
block start: food addr = 0x7f83aadc1c58, pFood addr = 0x7f83aadba148, animal addr = 0x7f83aadc4768
block start: food = 25, pFood = 0x0, animal = 0x7f83aadba150
block end: food addr = 0x7f83aadc1c58, pFood addr = 0x7f83aadba148, animal addr = 0x7f83aadc4768
block end: food = 15, pFood = 0x0, animal = 0x7f83aadbe270



结论:







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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值