在接触到开源项目 Masonry 后,里面的布局约束的链式写法让我颇感兴趣,就像下面这样:
1 2 3 4 5 6 7 8 | UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10); [view1 mas_makeConstraints:^(MASConstraintMaker *make) { make.top.equalTo(superview.mas_top). with .offset(padding.top); //with is an optional semantic filler make.left.equalTo(superview.mas_left). with .offset(padding.left); make.bottom.equalTo(superview.mas_bottom). with .offset(-padding.bottom); make.right.equalTo(superview.mas_right). with .offset(-padding.right); }]; |
其他语言比如 Lua, 实现链式语法很容易。但在 Objective-C 中,如何实现链式语法呢?
注:这里讨论的链式语法特指的是点链式语法,不同于中括号链式语法,如[[[[someObj method1] method2] method3] method4:someParam]。中括号链式语法相对而言更简单些,每个方法的返回值是下一个方法的发送者即可。
查看 Masonry 源码,起初没看明白,于是搜索了下 Stackoverflow,没有发现类似的问题,便将这个问题发布在了 Stackoverflow 上。这里是地址。
总结了下,贴下代码,做个说明。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | @class ClassB; @interface ClassA : NSObject // 1. 定义一些 block 属性 @property(nonatomic, readonly) ClassA *(^aaa)(BOOL enable); @property(nonatomic, readonly) ClassA *(^bbb)(NSString* str); @property(nonatomic, readonly) ClassB *(^ccc)(NSString* str); @implement ClassA // 2. 实现这些 block 方法,block 返回值类型很关键,影响着下一个链式 - (ClassA *(^)(BOOL))aaa { return ^(BOOL enable) { //code if (enable) { NSLog(@ "ClassA yes" ); } else { NSLog(@ "ClassA no" ); } return self; } } - (ClassA *(^)(NSString *))bbb { return ^(NSString *str)) { //code NSLog(@ "%@" , str); return self; } } // 这里返回了ClassB的一个实例,于是后面就可以继续链式 ClassB 的 block 方法 // 见下面例子 .ccc(@"Objective-C").ddd(NO) - (ClassB * (^)(NSString *))ccc { return ^(NSString *str) { //code NSLog(@ "%@" , str); ClassB* b = [[ClassB alloc] initWithString:ccc]; return b; } } //------------------------------------------ @interface ClassB : NSObject @property(nonatomic, readonly) ClassB *(^ddd)(BOOL enable); - (id)initWithString:(NSString *)str; @implement ClassB - (ClassB *(^)(BOOL))ddd { return ^(BOOL enable) { //code if (enable) { NSLog(@ "ClassB yes" ); } else { NSLog(@ "ClassB no" ); } return self; } } // 最后我们可以这样做 id a = [ClassA new ]; a.aaa(YES).bbb(@ "HelloWorld!" ).ccc(@ "Objective-C" ).ddd(NO) |