Objective-C语法
在Objective-C的语法中,是在众多语言中更加接近自然语言的,代码的可读性较高的。可是事情的都是双面性的。因为他使用的不是一般的开发语言的点链式语法,而是是使用了中括号链式语法。这就到导致了十分啰嗦和很长。
OC的中括号语法:
[[[object aFunc] bFunc] cFunc:@"String"]
点链式语法
object.aFunc(1).bFunc(1).cFunc("string")
Objective-C的链式语法介绍
OC中语法大致分为3种类型。
- 点语法【.】:一般用于属性的获取和设置。
- 中括号【[]】:一般用于方法的调用。
- 括号【()】 : 一般是block的调用。
无限点链式实现原理
从OC的语法中可以知道,要实现点链式语法,这就必须要借助于Block。
Block是一个匿名函数或者是一个函数指针,他可以携带参数同时也可以拥有返回值。
所以只要把Block的返回值都设置为当前类的的实例本身,这样就可以实现无限的调用了。
object.func1().func2(1).func(@"string")
实现的方式有两种:
- 定义只读的Block类型的属性,并把返回值类型设为当前类本身,然后实现这些 Block 属性的 getter 方法。
- 定义方法,然后通过方法的调用。
下面直接上代码:
DFPeople.h
//
// DFPeople.h
// ChainProgramming
//
// Created by raymond on 2021/3/24.
//
#import <Foundation/Foundation.h>
@interface DFPeople : NSObject
//第一种方法
//定义只读的Block类型的属性,并把返回值类型设为当前类本身,然后实现这些 Block 属性的 getter 方法。
@property (readonly, nonatomic, copy) DFPeople * (^salary)(NSInteger salary);
//第二种方法
//定义方法,然后通过方法的调用。
-(DFPeople* (^)(NSString *))myName;
@end
DFPeople.m
//
// DFPeople.m
// ChainProgramming
//
// Created by raymond on 2021/3/24.
//
#import "DFPeople.h"
@interface DFPeople()
@property (nonatomic, assign) NSInteger _salary;
@property (nonatomic, copy) NSString *name;
@end
@implementation DFPeople
-(instancetype) init{
self = [super init];
if(self){
}
return self;
}
-(DFPeople* (^)(NSString *))myName{
return ^id(NSString *name){
self.name = name;
NSLog(@"my name is %@",(self.name));
return self;
};
}
-(DFPeople * (^)(NSInteger salary))salary{
return ^id(NSInteger salary){
self._salary += salary;
NSLog(@"my salary is %@",(self._salary));
return self;
};
}
@end
调用:
//
// ViewController.m
// ChainProgramming
//
// Created by raymond on 2021/3/24.
//
#import "ViewController.h"
#import "DFPeople.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
DFPeople *people = [DFPeople new];
people.myName(@"Raymond").salary(1000);
}
@end
分析
DFPeople.h
// 在DFPeople.h头文件中,声明了一个copy属性的block变量。
// 设为readonly是为了限制只实现 getter 方法,同时防止被外部修改。
// 这里Block属性携带一个 NSInteger类型的参数,命名为salary(),而其返回值类型为当前 DFPeople,就是当前的类
@property (readonly, nonatomic, copy) DFPeople * (^salary)(NSInteger salary);
DFPeople.m
// 在DFPeople.m头文件中,实现.h文件中Block的getter的方法
// 而对于返回的 Block,其返回值类型为 DFPeople,所以在该 Block 里返回了 self。
-(DFPeople * (^)(NSInteger salary))salary{
return ^id(NSInteger salary){
self._salary += salary;
NSLog(@"my salary is %@",(self._salary));
return self;
};
}
所以在调用的时候 [DFPeople new].salary(1000),其实就是调用了[[DFPeople new] salary].然后返回一个 Block。如下:
return ^id(NSInteger salary){
self._salary += salary;
NSLog(@"my salary is %@",(self._salary));
return self;
};
这样当调用该 Block 时,会返回 self(即类实例本身),流程如下:
(1) DFPeople.salary -> 获得一个 Block;
(2) DFPeople.salary(1000) -> Block 的执行,并返回了 self(即实例 calc)
(3) 于是在 DFPeople.salary(1000) 后面可继续访问 DFPeople 的其他属性,实现无限点链。
一点点小的看法
在对于这种点链式语法的实现中,我更倾向于通过定义block的变量。因为这种在使用的时候,Xcode会给到代码提示。而如果使用方法定义模式,则不会有代码提示。如图:
定义block的变量
方法定义模式
完毕
这里就介绍完了OC实现点链式语法。如果能帮到你的话,麻烦点赞一下。谢谢
最后祝各位,代码永远没Bug,生活愉快~~~