可能被忽略掉编程技巧 之 链式编程

可能被忽略掉编程技巧 之 链式编程


@author Jou Email Weibo or Github


可能被忽略掉编程技巧 之 链式编程

预热 - 链式编程

哎呦,不错哦。有点时间, 随便写篇文章,聊聊iOS中的链式编程。
链式编程? 如果你不是iOS开发者,相信你应该没听过链式编程。对的, 链式编程,并不是一种编程范式。链式编程这种表述, 应该是在Objective-C独有,因为Objective-C是一门繁琐而奇怪的语言。
在Swift之前,想成为iOS开发者,在入门前你就有了两个门槛: 1. 你要有台苹果, 2. 你要肯于接受Objective-C的反人类,和繁琐。
所以形式上,链式编程是"点方法"的调用,来弥补Objc的繁琐。

Objective-C


NSString objc = @"Hello world";
[objc lowercaseString]; // 给objc 发送lowercaseString的消息

而相比之下swift 就更为简洁

let str = "Hello, playground"
str.lowercaseString;

链式编程 - 点式调用 LinkBlock

为了实现Objc中的点式调用, Novo已经有了一个基于block的好玩的实现LinkBlock
LinkBlock 旨在帮助我们实现点方法调用的happy path。
如:


UIButton* btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame= CGRectMake(20, 20, 150, 80);
UIColor *color = [UIColor colorWithRed:255/255.0 green:22/255.0 blue:150/255.0 alpha:1.0];
btn.backgroundColor = color;
[btn setTitle:@"click change color" forState:UIControlStateNormal];
[self.view addSubview:btn];


//如果使用链式编程的方式,大部分工作可以在思路连续的情况下进行
//now just using one line.Most work can be wrapped up in the idea of ​​ongoing cases
btn.viewSetFrame(20,20,150,80).viewBGColor(@"0xff22cc".strToColorFromHexStr())
.viewAddToView(self.view).btnTitle(@"click change color", UIControlStateNormal);

是不是简洁了许多。

链式编程 - Masonry

自从iOS设备尺寸多样化以后,为了适配大小屏,我们用到了autolayout。
即便是我们使用了VFL,官方的autolayout写法,在代码实现上也过于繁琐。
所以很大程度上, 一部分人转而重用storyboard界面布局,一部分转而重度依赖mansory, 还有大多数在结合使用。
而Masonry的实现上, 恰恰就是围绕Maker对象的链式编程。

之前autolayout的代码是这样的


UIView *superview = self;

UIView *view1 = [[UIView alloc] init];
view1.translatesAutoresizingMaskIntoConstraints = NO;
view1.backgroundColor = [UIColor greenColor];
[superview addSubview:view1];

UIEdgeInsets padding = UIEdgeInsetsMake(10, 10, 10, 10);

[superview addConstraints:@[

    //view1 constraints
    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeTop
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeTop
                                multiplier:1.0
                                  constant:padding.top],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeLeft
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeLeft
                                multiplier:1.0
                                  constant:padding.left],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeBottom
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeBottom
                                multiplier:1.0
                                  constant:-padding.bottom],

    [NSLayoutConstraint constraintWithItem:view1
                                 attribute:NSLayoutAttributeRight
                                 relatedBy:NSLayoutRelationEqual
                                    toItem:superview
                                 attribute:NSLayoutAttributeRight
                                multiplier:1
                                  constant:-padding.right],

 ]];

Masonry实现、

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);
}];

显而易见的、真是简洁到没朋友。

ps: Masonry 在github上 已有1W+的star。


除了形式上的链式调用, Objc中所谈的链式调用, 更是函数编程中一种常用的编程手段。

函数式编程 - Function Chaining

在swift中引入了函数式编程之后,把函数编程推到了新的高度。
而在swift中, 偶尔会见到这样的代码。


let result = students |> filterOutFailed |> sortByGrade |> formatForPrint |> joinByComma


把 ‘|>’ 换成 ’.' ,便有了极大的相似并不是偶然, 链式编程,只是函数编程思想的一种结合。

百分百的知识 - 实践 链式编程

如果团队有人在项目中,没有讨论的贸然加入了LinkBlock框架, 我肯定还是会argue一下的。
因过于依赖于LinkBlock,在代码可读性上增加了难度,并且增加了不可预期的崩溃。
LinkBlock中不能很好的处理,给nil进行链式调用,造成崩溃。

所以我认为,链式编程更好的实践,应该是应用在复用性较好的组件中, 最好还可以像masonry一样,使用block包裹起来。

如, 语句块在objc的使用方式之一:

self.tableView.tableFooterView = ({
  UIView *view = [[UIView alloc]initWithFrame:CGRectZero];
  view;
});

这不是纯秀技巧, 在代码可读性上, 他的模块, 和逻辑更加清晰。

所以我最近在考虑,将链式编程的思想加入我自己的 开源项目Router, 或 Dispatcher 中。 而形式上,则更类似Masonry的maker。

场景是 : 假如,我买了一架灰机, 我要驾驶它。

使用Block的特性,Trick实现链式调用

那么,我的飞机,一定可以起飞,降落, 上下左右,依照block的特性。我可以这么实现它


- (MAFlight *(^)(CGFloat distence))takeOff
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

- (MAFlight *(^)(CGFloat distence))landDown
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

- (MAFlight *(^)(CGFloat distence))forward
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

- (MAFlight *(^)(CGFloat distence))back
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

- (MAFlight *(^)(CGFloat distence))left
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

- (MAFlight *(^)(CGFloat distence))right
{
  return ^MAFlight *(CGFloat distence)
  {
    //Do move distence
    return self;
  };
}

所以我们就可以这么调用


MAFlight *flight = [[MAFlight alloc]init];//我买了飞机
flight.takeOff(10.f).forward(100000.f).left(10.f).right(1.f).back(1.f).back(1.f).landDown(10.f);

好了那么我们已经实现了链式调用,但,还没满足于此,因为逻辑还没有更加清晰。 为了叫买飞机的流程,和开飞机的流程更加清晰。实现了maker、

实现Maker

为了叫买飞机,我给NSObject实现了分类+Extra.h


+ (CGFloat)makeFlight:(void (^)(MAFlight *))block {

  //购买飞机
  MAFlight *maker = [[MAFlight alloc]init];
  //操作飞机
  block(maker);

  return maker.distence;
}

再为飞机加一点语法糖

- (MAFlight *)and
{
  return self;
}

所以, 就可以这么玩飞机了

[objc makeFlight:^(MAFlight *flight){
  flight.takeOff(10.f).and.forward(100000.f);
  flight.left(10.f).and.right(1.f);
  flight.back(1.f).and.back(1.f).landDown(10.f)
  }];

OK, That's all.

下一篇 - iOS Nightmare系列之 - 客户端应用的Daily Build 与 持续化集成(Continuous Integration)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 有很多想法 ,脑子里也有许多构思 。为什么不能写下来?书荒,可以写自己的小说。从现在开始
    文白__阅读 201评论 0 0
  • 文|杂家大兵 我不知道大家是否和我一样是一个疯狂收集信息的人,当想要了解一个领域或者一个行业的时候,通常会利用互联...
    杂家大兵阅读 956评论 0 3
  • 山下有芸芸众生,万千灯火山上有飘渺仙人,遗世独立2013-5-1 想象你站在山脚的一个小山坡上,正好可以被风吹到,...
    酒笑生阅读 149评论 0 1