block想必大家都很熟悉了,这就不在啰嗦概念了,直接上重点;今天聊聊block在平时开发中的三种用法:1.作为属性;2.作为参数;3.作为返回值 这三种用法。说这之前先说下xcode中自带的block代码块 inlineBlock
void(^hhblock)(void) = ^() {
NSLog(@"执行block");
};
hhblock();
打印结果
**2022-02-10 21:29:48.202772+0800 YTKRequestDemo[6629:289374] 执行block**
接下来给block添加返回值
int (^hhblock)(int a,int b) = ^(int a,int b) {
NSLog(@"执行block");
return a + b;
};
NSLog(@"%d",hhblock(10,20));
打印结果:
**2022-02-10 21:35:45.865788+0800 YTKRequestDemo[6752:294763] 执行block**
**2022-02-10 21:35:45.865966+0800 YTKRequestDemo[6752:294763] 30**
id (^hhblock)() = ^() {
NSLog(@"执行block");
NSString *str;
return str;
};
hhblock();
打印结果:
**2022-02-10 21:37:53.805888+0800 YTKRequestDemo[6796:296565] 执行block**
这些都正常运行但是return nil 时报错了
这是因为block值不知道你返回nil是怎么类型,这是在开发中经常会被忽略导致的错误,正确的写法应该是
id (^hhblock)(void) = ^id() {
NSLog(@"执行block");
return nil;
};
hhblock();
切记在block值中写上返回值,这是我们可以把inlinkblock代码块修改下做成自己的代码块
<#returnType#>(^<#blockName#>)(<#parameterTypes#>) = <#returnType#>^(<#parameters#>) {
<#statements#>
};
这个是我曾经犯过的错误,在这里写出来记录下,也许有小伙伴和我一样犯过这种错误,也让看到的小伙伴记住这个点。 接下来我们进入正题
block 作为属性
首先我们定义一个Person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^pblock)(void);
@end
viewcontroller 中调用
- (void)viewDidLoad {
[super viewDidLoad];
_p = [[Person alloc]init];
_p.run = ^{
NSLog(@"我跑起来了");
};
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
_p.run();
}
打印结果
**2022-02-10 22:19:01.811979+0800 YTKRequestDemo[7365:320911] 我跑起来了**
这是常见常用的一种方式,block作为属性。
blcok 作为参数
在person中定义一个方法
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^pblock)(void);
- (void)eat:(void(^)(void))block;
@end
#import "Person.h"
@implementation Person
- (void)eat:(void (^)(void))block{
NSLog(@"在person中调用你的block");
// 执行block
block();
}
@end
viewcontroller 中调用
- (void)viewDidLoad {
[super viewDidLoad];
_p = [[Person alloc]init];
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[_p eat:^{
NSLog(@"我吃过饭了");
}];
}
打印结果
**2022-02-10 22:32:31.444882+0800 在person中调用你的block**
**2022-02-10 22:32:31.445049+0800 我吃过饭了**
block 作为返回值
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^pblock)(void);
- (void)eat:(void(^)(void))block;
- (void)jump:(int)meter;
@end
调用jump方法
[_p jump:1];
这是简单的oc方法的调用方式,我现在在想还有其他调用方式吗?可不可以用点语言调用了,_p.jump();oc中的特性,get方法可以点出来,那接下来对代码进行修改
#import <Foundation/Foundation.h>
@interface Person : NSObject
- (int)jump;
@end
#import "Person.h"
@implementation Person
- (int)jump{
NSLog(@"哥们我跳了");
return 1;
}
@end
在viewController 中调用
_p.jump;
打印结果
**2022-02-10 23:00:22.588556+0800 YTKRequestDemo[8087:349861] 哥们我跳了**
这时候就是用点语法调用oc对象方法,做到这我在想怎么给方法中传递参数了? _p.jump 返回值是int,那把返回值改成block试试
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^run)(void);
- (void(^)(void))jump;// 返回一个无参数的block
@end
#import "Person.h"
@implementation Person
- (void (^)(void))jump{
// 返回一个block
return ^() {
NSLog(@"我执行了");
};
}
@end
viewController 中调用
// jump返回的是一个block,所以用block接收返回值
void(^jblock)(void) = _p.jump;
// 调用返回值block
jblock();
打印结果
**2022-02-10 23:08:16.528973+0800 YTKRequestDemo[8225:355730] 我执行了**
// block作为返回值是可行的,优化上面代码 _p.jump 返回的是个block,那可以直接优化为_p.jump();
_p.jump();
打印结果
**2022-02-10 23:14:01.390396+0800 YTKRequestDemo[8307:359088] 我执行了**
这时候就在想_p.jump();()括号中是可以用来传递参数的,()是block的,所以在返回值block中加入参数就可以
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^run)(void);
- (void(^)(int a))jump;// 返回一个无参数的block
@end
#import "Person.h"
@implementation Person
- (void (^)(int a))jump{
// 返回一个block
return ^(int a) {
NSLog(@"我跳了%d米高",a);
};
}
@end
viewController 中调用
_p.jump(1);
打印结果
**2022-02-10 23:17:37.761479+0800 YTKRequestDemo[8388:362375] 我跳了1米高**
这就是block作为返回值的用法;看到这种写法,大家应该想到了masonry了吧,masonry就是这样写的,但是masonry可以无限的点下去;那我们接着修改代码;分析:jump是对象p的方法,只有p能点出来,那_p.jump(1)执行完返回一个p对象,那就能继续执行下去了
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) void(^run)(void);
- (Person *(^)(int a))jump;// 返回一个无参数的block
@end
#import "Person.h"
@implementation Person
- (Person *(^)(int a))jump{
// 返回一个block
return ^(int a) {
NSLog(@"我跳了%d米高",a);
return self;
};
}
@end
viewController 中调用
_p.jump(1).jump(2).jump(3);
打印结果
**2022-02-10 23:23:59.868825+0800 YTKRequestDemo[8498:366488] 我跳了1米高**
**2022-02-10 23:23:59.869185+0800 YTKRequestDemo[8498:366488] 我跳了2米高**
**2022-02-10 23:23:59.869362+0800 YTKRequestDemo[8498:366488] 我跳了3米高**
完美实现了block最为返回值的使用方法;接下来发现一个问题
点出方法来没有要传参数的提示,继续修改
#import <Foundation/Foundation.h>
@class Person;
typedef Person *_Nullable (^PersonBlock)(int a);
@interface Person : NSObject
@property (nonatomic,copy) PersonBlock runblock;
@end
#import "Person.h"
@implementation Person
- (PersonBlock)runblock{
// 返回一个block
return ^(int a) {
NSLog(@"我跳了%d米高",a);
return self;
};
}
@end
#import "Person.h"
@implementation Person
- (Person *(^)(int a))jump{
// 返回一个block
return ^(int a) {
NSLog(@"我跳了%d米高",a);
return self;
};
}
@end
viewController 中调用
_p.runblock(1).runblock(2);
打印结果
**2022-02-10 23:35:33.596224+0800 YTKRequestDemo[8683:374134] 我跳了1米高**
**2022-02-10 23:35:33.596364+0800 YTKRequestDemo[8683:374134] 我跳了2米高**
把方法改成属性,在调用的时候就有了参数怎么传的提示了。
一直用点语法点下去这种方式叫链式编程
链式编程+block封装UIkit
最后我自己基于UIKit封装的基础控件库,使用链式编程思想+block对常用的控件进行封装,包含UIView,UILabel,UIButton,UITextFiled,UITextView,UITableView的封装HHBlockKit 欢迎大家下载看看,有问题一起讨论,小弟不才,咱们一起研究,若觉得对你有用请给个star😁。