Block 是一种苹果开发的基于 C 的调用方式,在 iOS 和 Mac 开发上都有广泛的应用。Block 从某种程度上来说是一种很新的回调方式,苹果在2009年将其引入 Mac OS X 10.6,之后在2010年将其引入到 iOS 4.0。
在iOS开发过程中,回调方式有三种Block、Delegate、NSNotification。这三种方式也是各有优缺点,这里只是讲一下Block的几种用法。什么东西都有优点和缺点,就像我除了帅就一无所有,所以的话,我们的Block也是一样的。
循环引用的解决方式就是,外部用__weak typeof(self) weakSelf = self; __weak修饰一下,使外部的self对象能够释放,在Block内部__strong typeof(self) self = weakSelf; __strong修饰一下,让内部能够拿到self对象就OK了。
第一种用法:作为属性传值
应用场景:比如界面之间反向传值
创建一个Person类
#import
/*
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 *)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
@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
@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
@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