mas&链式编程思想(代码片段)

byxixiblogs byxixiblogs     2023-01-16     799

关键词:

前言:编程思想在iOS的应用中大概有那么几类,我们最常用的当属于面向对象的编程思想,一切皆对象,基于这种思想离不开的就是我们最常用的封装、继承、多态。平时工作中我们也会接触一些面向协议的编程思想,比如说接口分离解耦合,再比如说我们最常用的delegate都是面向协议的思想,还有就是基于ReactiveCocoa框架也就是平时听到的RAC提供的响应式编程思想,今天主要分析下另一种编程思想,链式编程。

 

首先简单分析一下Masonry的实现过程:

- (NSArray *)mas_makeConstraints:(void(^)(MASConstraintMaker *))block 
    self.translatesAutoresizingMaskIntoConstraints = NO;
    MASConstraintMaker *constraintMaker = [[MASConstraintMaker alloc] initWithView:self];
    block(constraintMaker);
    return [constraintMaker install];


- (id)initWithView:(MAS_VIEW *)view 
    self = [super init];
    if (!self) return nil;
    self.view = view;
    self.constraints = NSMutableArray.new;
    return self;

1.创建约束制造者MASConstraintMaker并且绑定控件,在约束制造者init的同时生成了一个保存所有约束的数组constraints

2.执行mas_makeConstraints传入的block,返回我们刚才创建的约束制造者constraintMaker

3.让约束制造者安装约束,执行install方法。

我们再看一下install里面做了什么:

- (NSArray *)install 
    if (self.removeExisting) 
        NSArray *installedConstraints = [MASViewConstraint installedConstraintsForView:self.view];
        for (MASConstraint *constraint in installedConstraints) 
            [constraint uninstall];
        
    
    NSArray *constraints = self.constraints.copy;
    for (MASConstraint *constraint in constraints) 
        constraint.updateExisting = self.updateExisting;
        [constraint install];
    
    [self.constraints removeAllObjects];
    return constraints;

实际上是遍历了我们创建约束制造者constraintMaker时所创建的constraints,constraints里面实际上存储的是我们为控件添加的所有约束信息,然后分别对每条约束之行install。那么问题来了,constraints里面的约束从哪里来的呢。这就要回到了上面说的第2步,block将约束制造者返回给用户,让用户通过constraintMaker去设置控件的约束,这些约束实际上就是存储到了constraints中。当执行第3步return [constraintMaker install];的时候,就是将所有调用者添加的布局转换为NSLayoutConstraint对象也就是我们熟悉的纯代码适配,进行布局更新。

 

那么为什么学习链式编程思想我们要先研究下Masonry呢,因为Masonry就是基于链式编程思想实现的开源框架,即强大,又直观。比如说我们在使用Masonry的时候通常会这样写:

[view mas_makeConstraints:^(MASConstraintMaker *make) 
    make.height.top.mas_equalTo(44);
    make.left.mas_equalTo(5);
    make.centerY.equalTo(self);
];

为什么make可以一直这么点下去,点语法给我们的第一感觉是get方法,实际上确实是get方法:

- (MASConstraint *)height 
    return [self addConstraintWithLayoutAttribute:NSLayoutAttributeHeight];

通过源码可以看到.height实际上返回的并不是一个int或者NSInteger类型变量,而是MASConstraint,是约束制造者本身,实际上每次调用.height就是将约束添加到我们上面提到的constraints数组中。到这里,链式编程的特点就显而易见了,那就是方法返回值必须要有方法的调用者。那么还有疑问,mas_equalTo()是什么鬼。下面着重讲一下.mas_equalTo(),

还是通过源代码点进去看一下:

- (MASConstraint * (^)(id))equalTo 
    return ^id(id attribute) 
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    ;

返回值是一个MASConstraint * (^)(id) 的block类型,到这里我们了解了.mas_equalTo实际上是返回了一个返回值为MASConstraint类型的block,当我们外面调用block的时候实际上之行的是

self.equalToWithRelation(attribute, NSLayoutRelationEqual);函数,没错,它返回的依旧是MASConstraint类型,依旧是方法的调用者,也就是前面提到的约束制造者,所以我们在调用mas_equalTo()之后还能继续点下去,像不像个无底洞。如果这样不好理解的话我们可以将添加约束的源码改写一下来实现:

[view mas_makeConstraints:^(MASConstraintMaker *make) 
//     make.height.top.mas_equalTo(44);
    MASConstraint * (^)(id)block = make.height.top.mas_equlTo;
    MASConstraint *make = block(44);
    make.top...
];

这下应该就很好理解了。

最后总结一下什么是链式编程,总结一句话就是方法返回值必须要有方法的调用者!

链式编程:泛型实现的扩展方法类

序言本文分享一个用链式编程思想和泛型实现的扩展方法类,用于减少代码量,并提供更为清晰的业务逻辑代码表达。概念链式编程:将多个业务逻辑(方法)通过“.”(点号)串联起来的一种代码风格,形似链条,故称链... 查看详情

java链式编程/级联式编程(代码片段)

链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。链式编程:通过高阶函数以点为连接将多个函数连接在一起完成参数传递和复杂的操作!通... 查看详情

java链式编程/级联式编程(代码片段)

链式编程,也叫级联式编程,调用对象的函数时返回一个this对象指向对象本身,达到链式效果,可以级联调用。链式编程:通过高阶函数以点为连接将多个函数连接在一起完成参数传递和复杂的操作!通... 查看详情

链式向前星知识点&代码(代码片段)

代码:structNODEintto;intnxt;intc;node[MM];//链式向前星inthead[NM],lcnt=1;voidadd(inta,intb,intc)node[lcnt].to=b;node[lcnt].c=c;node[lcnt].nxt=head[a];head[a]=lcnt++;显示神奇代码 1.使用结构体构建链式向前星的容器链式向前星本质上是 查看详情

scala链式编程内幕(代码片段)

1packagebig.data.analyse.scala23/**4*链式编程原理5*Createdbyzhenon2018/12/16.6*/7classComputerdefcode=this8classPCextendsComputerdefportable=this9/**10*使用type可以根据当前情况转化类型实现链式编程11*/12classCardefrun:this.type=this13classRoadsterextendsCardefluxury:this.typ... 查看详情

ruby使用`&`创建块时可以进行链式调用(代码片段)

查看详情

golang面向对象编程思想(代码片段)

抽象介绍:  在定义一个结构体的时候,实际上就是把一类事物的共有属性(字段)和行为(方法) 提取出来,形成一个物理模型(模板),这种研究问题的方法称为抽象。封装:  把抽象出的字段和对字段的操作封装... 查看详情

正则运用&链式调用的典型例题(代码片段)

典型面试题,编写满足下列要求的函数考察点javascript基础正则表达式链式调用//约定://title数据类型为String//userId为主键,数据类型为Numbervardata=[userId:8,title:'title1',userId:11,title:'other',userId:15,title 查看详情

rxjava编程思想2-(实现简易版rxjava,如何实现操作符?)(代码片段)

...文目的是通过几百行的代码,帮助大家理解rxjava中的链式调用,操作符,线程切换是如何实现的。如果有写的不对的地方欢迎在评论区留言,如果觉得写的可以,请点赞,关注,谢谢。代码链接:gi... 查看详情

rxjava编程思想3-(实现简易版rxjava,如何实现线程切换)(代码片段)

...文目的是通过几百行的代码,帮助大家理解rxjava中的链式调用,操作符,线程切换是如何实现的。如果有写的不对的地方欢迎在评论区留言,如果觉得写的可以,请点赞,关注,谢谢。代码链接:gi... 查看详情

贝叶斯推断&&概率编程初探(代码片段)

...的思想我们从一个例子开始我们本文的讨论。小明是一个编程老手,但是依然坚信bug仍有可能在代码中存在。于是,在实现了一段特别难的算法之后,他开始决定先来一个简单的测试用例,这个用例通过了。接着,他用了一个稍... 查看详情

rxjava编程思想2-(实现简易版rxjava,如何实现操作符?)(代码片段)

...文目的是通过几百行的代码,帮助大家理解rxjava中的链式调用,操作符,线程切换是如何实现的。如果有写的不对的地方欢迎在评论区留言,如果觉得写的可以,请点赞,关注,谢谢。代码链接:gi... 查看详情

编程思想:巧用位运算重构代码(代码片段)

开篇在一门编程语言中,往往会提供大量的运算符。按功能来分的话,有算术运算符、赋值运算符、关系运算符、逻辑运算符、位运算符等。这些对于大家来说都不陌生。但是,本期的主角『位运算』符相对而言是比较少去使用... 查看详情

[编程题]lk[231.2的幂](代码片段)

[编程题]lk231.2的幂题目输入输出方法1:位运算//方法3:使用位运算消除1/*思想:如果是2的n次方,那么它的二进制肯定是0000000100000这种样子,其中是只有一个1(有可能是0000001),我们用位运算消除一次,看能否消除为0,就判断是... 查看详情

[jquery]jquery链式编程(代码片段)

链式编程节约代码量<button>快速</button><button>快速</button><button>快速</button><button>快速</button><button>快速</button><button>快速</button><button>快速</button><script>$(function()//... 查看详情

java编程思想:通配符(后面有两个小节,研究的不够深入)(代码片段)

importjava.util.*;publicclassTestpublicstaticvoidmain(String[]args)/*15.9边界要点:1.T继承的顺序,类放必须放在第一位,后面跟接口2.类与接口用&进行链接3.可以继承于一个类,可以实现多个接口4.可以使用边界类的方法5.可以使用边界类的... 查看详情

编程思想(代码片段)

面向对象编程的思想  做一件事情,找一个能解决这个事情的对象,调用对象的方法,完成事情函数式编程思想  只要能获取到结果,谁去做的,怎么做的都不重要,重视的是结果,不重视过程 匿名内部类  匿名内部... 查看详情

22.仿淘宝五角星评论(链式编程隐式迭代)(代码片段)

试玩(淘宝案例在下面):效果:<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title></title><scriptsrc="../jquery-3.3.1.min.js"></script><style>*margin 查看详情