iOS - Block 用法及其应用场景概述。

Block 是一种苹果开发的基于 C 的调用方式,在 iOS 和 Mac 开发上都有广泛的应用。Block 从某种程度上来说是一种很新的回调方式,苹果在2009年将其引入 Mac OS X 10.6,之后在2010年将其引入到 iOS 4.0。

在iOS开发过程中,回调方式有三种BlockDelegateNSNotification。这三种方式也是各有优缺点,这里只是讲一下Block的几种用法。什么东西都有优点和缺点,就像我除了帅就一无所有,所以的话,我们的Block也是一样的。

  1. Block的优点:方便、简单、快速回调、代码可读性强,尤其处理异步逻辑的时候让你爽的不要不要的。
  2. Block的缺点:
    (1)由多个相关方法。假如每个方法都设置一个block,这样就会很麻烦,这时候就要考虑Delegate。Delegate让多个方法分成一组,只需要设置一次代理就可以完成多次回调。
    (2)循环引用的问题,其实代理用strong修饰(上篇文章讲到的)也同样会有循环引用,但是block更容易产生!因为使用Block的时候稍微不注意可能就会导致对象是放不了,而且一旦出现就比较难检查出来,后果是毁灭性的。但是这个问题是我们完全可以避免的。

循环引用的解决方式就是,外部用__weak typeof(self) weakSelf = self; __weak修饰一下,使外部的self对象能够释放,在Block内部__strong typeof(self) self = weakSelf; __strong修饰一下,让内部能够拿到self对象就OK了。

第一种用法:作为属性传值
应用场景:比如界面之间反向传值

创建一个Person类

#import <Foundation/Foundation.h>
/*
 typedef 定义一个blcok
 */
typedef void (^block) (NSString * name,NSInteger age);

@interface Person : NSObject

@property (nonatomic,strong)block myBlock; //设置一个blcok属性

@end

VC中的代码如下:

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
/**    */
@property (nonatomic,strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Person * p = [[Person alloc]init];

    //block 回调
    p.myBlock = ^(NSString *name, NSInteger age) {

        NSLog(@"我的名字叫%@ 今年%ld岁了",name,age);
    };

    _p = p;

}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{

    //block 传进两个参数
    NSString * name = @"LY";
    NSInteger age = 18;

    _p.myBlock(name, age);
}

这样当我惦记屏幕的时候Block就会回调打印:

2017-06-29 14:08:51.070 BlockCircularReferenceDemo[4968:12856691] 我的名字叫LY 今年18岁了

第二种用法:作为方法的参数,主要是外界不能调用,只能在这个方法内部调用,用于回调合传值等。

应用场景:比如网络请求(AFN)

同样是Person类

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface Person : NSObject


-(void)run:(void(^)())runBlock;

@end
-(void)run:(void(^)())runBlock{

    NSLog(@"一起跑步吧!");

    runBlock();

}

VC里面的代码如下:

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
/**    */
@property (nonatomic,strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Person * p = [[Person alloc]init];


    [p run:^{

        NSLog(@"跑完洗澡澡");
    }];




}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

打印结果:

2017-06-29 15:12:52.742 BlockCircularReferenceDemo[5096:12936446] 一起跑步吧!
2017-06-29 15:12:52.742 BlockCircularReferenceDemo[5096:12936446] 跑完洗澡澡

把Block作为参数,先执行-(void)run:(void(^)())runBlock;这个方法,等这个方法执行完之后就回调会VC里面的 NSLog(@”跑完洗澡澡”);这句代码。

第三种用法:作为方法的返回值,内部不能调用,只能外界调用。

应用场景:Masonry 的用法 ,链式编程的思想。

还是我们的Person类:

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface Person : NSObject


- (void(^)())run;

@end
//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "Person.h"

@implementation Person

- (void(^)())run{

    return ^(){

        NSLog(@"跑了10圈了");
    };

}


@end

VC代码如下:

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
/**    */
@property (nonatomic,strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Person * p = [[Person alloc]init];

    //直接用点语法调用run方法,很几把屌是不是! ()里面可以穿参数的呦!
    p.run();

}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

打印:

2017-06-29 15:35:45.464 BlockCircularReferenceDemo[5263:12967469] 跑了10圈了

那么接下来,玩一个变态用法,链式编程用法:

//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import <Foundation/Foundation.h>


@interface Person : NSObject

//这个run方法的返回值是一个 block ,那么这个block的返回值是 - 方法的调用者 p 对象的类型 Person *
- (Person *(^)(int a))run;

@end
//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "Person.h"

@implementation Person


- (Person * (^)(int a))run{

    //这个方法返回一个block
    return ^Person *(int a){


        NSLog(@"跑了%d圈了",a);


       //block的返回值是 self (Person * 类型)
        return self;
    };

}


@end
//  Created by cuzZLYues on 2017/6/28.
//  Copyright © 2017年 cuzZLYues. All rights reserved.
//

#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
/**    */
@property (nonatomic,strong) Person *p;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    Person * p = [[Person alloc]init];

    /*
     现在我传一个参数!

     p.run 这一步是一个get方法他的返回值是一个带参数的block,也就是这一坨:

     return ^Person *(int a){

     NSLog(@"跑了%d圈了",a);

     //block的返回值是 self (Person * 类型)
     return self;
     };

     p.run(10) 到了这一步,它的返回值就是一个Person对象,所以怎么样,我们能继续点语法一直点点点。。

     p.run(10).run(19).run(20);
     */
    p.run(10).run(19).run(20);

}



- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


@end

看到注释应该很清楚啦吧,这就是链式编程的思想,以上就是Block的几种玩法啦,希望大家多多支持一下,多多评论,我们互相交流和学习!

最后全部代码在这里:https://github.com/yueShenAAA/BlockUtilize

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值