有一句话叫三人行必有我师,其实作为一个开发者有一个学习的氛围跟一个交流圈子特别重要,这是我的一个iOS交流群686183764,不管是小白还是大牛都欢迎入驻,大家一起交流成长!话糙理不糙,互相学习,共同进步!一起加油吧!
链式编程思想:是将多个操作(多行代码)通过点号(.)链接在一起成为一句代码,使代码可读性好。a(1).b(2).c(3);链式编程特点:方法的返回值是block,block必须有返回值(本身对象),block参数(需要操作的值)代表:Masonry框架。
OC最令人头疼的是他看起来像部落语言一样的表达。比如下面这行新手代码:
[[NSMutableDictionary alloc] initWithContentsOfURL:[NSURL URLWithString:@"url"]];
非常的长,在其他语言里可以这样写,NSMutableDictionary(NSURL(@"url"))。语言发展到今天,代码的普世价值不是效率,而是开发效率。这就是为什么java能够成为王者的原因。因为java写起来快,好读。
objc比起java又慢又不好读。那么如何让OC看起来像java一样呢。纵观OC全部语法,只有block能够办到。我们来看block的定义
returnType (^name) (val1, val2, ...);
block具有一个函数的外观,又被当作一个变量。那么block就具备两个功能
第一:可以作为类的属性被'点'出来。
第二:可以当作函数直接调用。
下面逐个解释,第一个类的属性可以点出来,比如person.name;这很好理解,你一定见过,str.length;对吧。第二个呢,block作为一个变量,但是又可以把它当作指向函数的指针一样调用。
NSString(^myBlock)() = ^(){ return @"str"; };
//定义一个返回值为NSString类型,无参的,并且名字叫做myBlock的blockmyBlock();
//这一行就是调用NSString result = myBlock();
//这是取出block执行后拿到的返回值,这里再解释一次block的定义:上面的myBlock可以认为是指向一个定义如下的函数的指针,这个函数是(NSString) myBlock()
现在开始来模拟实现链式编程语法,先定义一个block:typedef ClassA *(^ConfigBlock)(NSString *name);给ClassA加一个属性,重写get方法返回这个block,在block内部给name赋值并返回self。如下:
@interface ClassA : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) ConfigBlock cfgName;
@end
@implementation ClassA
- (ConfigBlock)cfgName{
return ^(NSString *name){
self.name = name;
return self;
};
}
@end
这样在外部就可以用instance.cfgName(@"罗辑")了;这个表达式返回的是ClassA的实例,可以接着调用其他的方法或属性。这里简单实现就不展开了
尽管第一次开发非常麻烦,不过完成之后再调用时非常爽的,对比就是Masonry框架,用原来的OC去实现非常的繁琐,以至于苹果刚刚推出时很多程序员都不愿意去使用Autolayout。Masonry用链式封装之后设置大量的约束就不用写海量的代码了。
不过在第一次开发的时候还是有点麻烦,要先定义一个block,如果属性非常多,非常的麻烦,有没有可以省事一点的方法呢。
NerdyUI是一个用链式语法开发的OC库,对于常用的UI的封装非常的完善,例如创建一个Label
Label.color(Color(@"#efefef")).fnt(16).str(@"NerdyUI").xywh(0,0,60,20).addTo(self.view);
既然是UI库,Autolayout肯定支持。同样,也可以用它来添加约束
self.titleLabel = Label.color(Color(@"#efefef")).fnt(16).addTo(self.backgroundImgView).updateCons(^{
语法和Masonry差不多,熟悉Masonry的同学可以直接过渡。当然这次不是介绍NerdyUI的,关于它的介绍,网上有很多,本身的文档也很详细。我们可以利用NerdyUI封装的一些宏来节省一些时间,
NERDefs.h里定义了需要用到的宏,还以上个例子为例
NER_GENERATE_CHAINABLE_TYPES(ClassA);
@interface ClassA : NSObject
@property (nonatomic, copy) NSString *name;
NER_PROP(ClassA, Object) cfgName;
@end
@implementation ClassA
- (NERChainableClassAObjectBlock)cfgName{
return ^(NSString *name){
self.name = name;
return self;
};
}
@end
NER_GENERATE_CHAINABLE_TYPES(ClassA);可以把我们将要使用到的block都定义好,
NER_PROP(ClassA, Object) cfgName;设置属性,这样就可以节省很多代码了,只需要重写一下get方法就可以了。
有一句话叫三人行必有我师,其实作为一个开发者有一个学习的氛围跟一个交流圈子特别重要,这是我的一个iOS交流群686183764,不管是小白还是大牛都欢迎入驻,大家一起交流成长!话糙理不糙,互相学习,共同进步!一起加油吧!
网友评论