Block 基本使用介绍

block在iOS中是一个神奇的存在,既像是面向过程的函数又像是面向对象的对象实例,实质上是一个匿名函数.如果能够很好的利用它就就可以很方面地控制数据流程,使代码结构更加清晰,逻辑实现更加明了易读.

1 如何定义一个Block

  • 直接在使用的地方定义

例如我们需要一个没有返回值没有参数的block:如果参数为空,后边的()可以省略.

void (^blockWithNoValueAndParameter)(void) = ^(){
    //code here do what you want
};
或者
void (^blockWithNoValueAndParameter)(NSString *) = ^{
    //code here do what you want
    
};

或者需要一个有参数无返回值的block:

void(^blockWithNoValueBlock)(NSString *) = ^(NSString *str) {
    NSLog("content == %@", str);
};

或者有参数有返回值的block:

NSString *(^block)(NSString *) = ^NSString *(NSString *str) {
    NSString *_str = str;
    if (![_str hasPrefix:@"_aspects_"]) {
        _str = [@"_aspects_" stringByAppendingString:_str];
    }
    return _str;
};
  • 使用typedef预先定义block
        typedef NSInteger (^GetLengthBlock)(NSString *);

        GetLengthBlock block = ^NSInteger(NSString *str){
            return str.length;
        };

可能有人注意到了,为什么在上边的定义中我们都使用了小写开头,而这里使用大些开头呢?这是因为typedef定义的是一个"类"(此时的GetLengthBlock相当于 NSInteger (^)(NSString *)  这个结构),而不是一个具体的block,而上边我们只是定义一个具体的block(相当于 (NSInteger (^)(NSString *))block),虽然看起来差不多,但事实上代表的意义是不一样的.

2. Block的使用场景

2.1  作为属性进行传值

例如我们可以在一个控制器中定义一个属性block,在给界面push之前定义block的实现,然后在该界面发生的事件就可以通过block进行回传.

@interface ViewController ()
//由于block绝大多数情况下会需要捕获外部变量,所以一般使用block修饰,将block从栈区copy到堆区,方便控制其生命周期
@property (copy, nonatomic) void(^sendValueBlock)(id);
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    if (self.sendValueBlock) {
        self.sendValueBlock(@"touch");
    }
}

注意:我们将block视为对象,由于block绝大多数情况下会需要捕获外部变量,所以一般使用block修饰,将block从栈区copy到堆区,方便控制其生命周期,防止其提前释放造成野指针异常.

2.2 作为参数进行回调

例如,AFNetworking中AFHTTPSessionManager中GET方式请求的数据回调,可以在需要的时候进行回调.

- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
                            parameters:(nullable id)parameters
                              progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
                               success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
                               failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;

2.3 实现链式编程

可以通过定义属性block来实现函数的链式调用,例如著名的布局框架masnory就是借助于block实现的,我们这里制作简单的说明.例如我们做一个简单的加减法运算器:

@interface Calculator : NSObject
@property (assign, nonatomic) double result;
- (Calculator *(^)(double num))add;
- (Calculator *(^)(double num))sub;

@end

@implementation Calculator
- (Calculator *(^)(double num))add {
    return ^Calculator *(double num) {
        self.result  += num;
        return self;
    };
}
- (Calculator *(^)(double num))sub {
    return ^Calculator *(double num){
        self.result -= num;
        return self;
    };
}
@end


    Calculator *cal = [[Calculator alloc] init];
    cal.add(30).sub(3).add(23);

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值