🔗 链式调用的本质
通过方法返回 Block,且 Block 的返回值是对象自身,实现连续的点语法调用:
person.run(@"跑步").eat(@"苹果").sleep();
🛠 实现步骤(以 Person 类为例)
1. 定义链式方法
// Person.h
@interface Person : NSObject
// 无参数方法
- (Person *(^)(void))run;
- (Person *(^)(void))eat;
// 带参数方法
- (Person *(^)(NSString *food))eatWithFood;
- (Person *(^)(NSInteger hours))sleep;
@end
2. 实现 Block 方法
// Person.m
@implementation Person
// 无参方法
- (Person *(^)(void))run {
return ^{
NSLog(@"开始跑步");
return self; // 关键:返回对象自身
};
}
// 带参数方法
- (Person *(^)(NSString *))eatWithFood {
return ^(NSString *food) {
NSLog(@"吃 %@", food);
return self;
};
}
// 链式终止方法(无返回值)
- (void (^)(void))sleep {
return ^{
NSLog(@"睡觉8小时");
};
}
@end
🔍 调用示例
Person *person = [[Person alloc] init];
// 传统调用方式
[person run];
[person eatWithFood:@"苹果"];
[person sleep];
// 链式调用方式
person.run().eatWithFood(@"苹果").sleep();
// 混合参数调用
person.eatWithFood(@"香蕉").run().eatWithFood(@"苹果")();
⚙️ 实现原理
-
方法返回 Block:
- 方法签名格式:
- (返回类型 (^)(参数类型))方法名 - 例如:
- (Person *(^)(NSString *))eatWithFood
- 方法签名格式:
-
Block 内部逻辑:
- 执行具体操作(如打印日志、修改对象状态)
- 返回
self保证链式连续性(终止方法除外)
-
ARC 内存管理:
- Block 捕获
self时默认强引用 - 需用
__weak避免循环引用:__weak typeof(self) weakSelf = self; return ^{ __strong typeof(weakSelf) strongSelf = weakSelf; [strongSelf doSomething]; return strongSelf; };
- Block 捕获
📝 高级技巧
1. 支持多参数
- (Person *(^)(NSString *, NSInteger))action {
return ^(NSString *name, NSInteger count) {
NSLog(@"执行%@ %zd次", name, count);
return self;
};
}
// 调用
person.action(@"深蹲", 10);
2. 与建造者模式结合
Person.newBuilder
.name(@"张三")
.age(25)
.address(@"北京")
.build();
3. 链式终止设计
- (void)build {
NSLog(@"对象构建完成");
}
// 调用
person.configA().configB().build();
🚧 注意事项
- 避免循环引用:在 Block 内使用
__weak弱引用 - 方法命名规范:使用动词短语(如
withXxx、enableXxx) - 调试技巧:用
NSLog(@"%@", [block class])查看 Block 类型 - 性能优化:频繁调用的 Block 建议缓存(
static dispatch_once_t)
🌰 完整示例(配置对象)
// Config.h
@interface Config : NSObject
- (Config *(^)(BOOL))enableLog;
- (Config *(^)(NSString *))setHost;
@end
// Config.m
@implementation Config {
BOOL _enableLog;
NSString *_host;
}
- (Config *(^)(BOOL))enableLog {
return ^(BOOL enable) {
_enableLog = enable;
return self;
};
}
- (Config *(^)(NSString *))setHost {
return ^(NSString *host) {
_host = [host copy];
return self;
};
}
@end
// 使用
Config.new.enableLog(YES).setHost(@"https://api.example.com");
参考 Masonry