美文网首页iOS开发系列超棒文集链式编程
可能被忽略掉编程技巧 之 链式编程

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

作者: JARVIS_STUDIO | 来源:发表于2016-03-21 16:08 被阅读700次

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


@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)

相关文章

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

    可能被忽略掉编程技巧 之 链式编程 @author Jou Email Weibo or Github 可能被忽略...

  • 工作iOS技术总结

    链式编程、函数式、面向接口编程思想 iOS 之ReactiveCocoa 链式编程2 WKWebView的缓存处理...

  • jQuery 链式编程

    jQuery 链式编程 链式编程原理 链式编程代码示例 隐式迭代

  • iOS 链式编程

    链式编程 主要介绍链式编程原理,以及如何创建链式编程 编程范式 在介绍链式编程之前,首先来了解下什么是编程范式。 ...

  • 链式编程思想

    链式编程思想 链式编程思想

  • iOS开发之链式编程

    很多小伙伴在开发的过程当中会见到一个很神秘的词--链式编程,那么到底什么是链式编程,链式编程到底有什么神奇之...

  • ReactiveObjC入门

    ReactiveObjC基础用法 iOS开发三种编程方式(响应式编程、函数编程、链式编程),函数编程最常用,链式编...

  • iOS-链式编程

    函数式编程------->链式编程 函数式编程: 调用方式 我们最终目的是将函数式编程转换为链式编程:首先将调用方...

  • 一、链式编程思想、响应式编程思想和函数式编程

    1. 链式编程思想 链式编程思想的核心就是方法的返回值必须是Block,Masonry是链式编程思想应用的代表。 ...

  • 链式编程和函数式编程的简单理解

    链式编程 此前看到SnipKit中运用了很多链式编程的代码,感觉非常好用:例如: //此段就是链式编程的典型代码m...

网友评论

本文标题:可能被忽略掉编程技巧 之 链式编程

本文链接:https://www.haomeiwen.com/subject/jpphlttx.html