Masonry和链式编程

转自
Objective-C 链式编程
最近看到了链式编程和函数式编程这两个概念,网上查了一些资料,但是发现资料都千篇一律,我心中存在的这几个疑惑根本没有帮我解开。
1,为什么可以使用.语法来调用方法,而不是使用OC里面的[ ]。
2,为什么方法里面明明没有参数,当方法的返回值是一个block时,使用.语法调用方法可以传参数。
不知道有没有和我遇到一样的问题的同学,周末的时间用了一个下午一点一点琢磨。下面我来一一解释这些问题。
首先,先简绍下block

block的作用,主要用于回调传值,解耦合
1.当方法的参数是block类型,block的参数用于从内向外传值
2.block的返回值用于从外向内返回结果

这两句话是能实现链式编程的关键,好好理解下。

对于block,我们可以这样理解
举个例子:大家想必都看过警匪片,在片子里面,坏蛋都喜欢安装一些遥控的炸弹来威胁警察,如果警察不听话,坏蛋就会引爆炸弹。这里的炸弹就可以理解为block,而遥控器就可以理解为调用block。block就是我们提前存储的一段代码块,当我们需要使用的时候才去调用它。下面来看一段网络请求数据的代码来理解下这个遥控炸弹。

@interface ReuuestData : NSObject

//定义无参数无返回值的block

  • (void)requestDataSucc:(void(^)())succBlock fail:(void(^)())failBlock;
    @end
    @implementation ReuuestData
  • (void)requestDataSucc:(void (^)())succBlock fail:(void (^)())failBlock {
    //这一块就相当于炸弹的遥控器, 在成功或者失败里引爆炸弹
    if (/* DISABLES CODE */ (YES)) {
    succBlock(); //成功的block
    }else {
    failBlock(); //失败的block
    }
    }
    @end
    下面我们在ViewController里使用下

ReuuestData *obj = [ReuuestData alloc] init];
//这一块就相当于埋了一个炸弹, 我们不管他什么时候会爆炸,决定他爆炸的时刻是安装了这个炸弹接收信号的遥控器
[obj requestDataSucc:^{
//成功的回调
} fail:^{
//失败的回调
}];
因为我们在进行网络请求时不知道什么时候请求会成功, 我们首先让obj 调用请求网络的方法, 此时,开始网络请求, 当请求结束后,会走对应的成功或者失败的方法。

接下来理解了上面的网络请求的例子,咱们就以一个例子来讲解链式编程,这个例子在其他文章中也都有介绍,为了保证文章的完整性,我就再啰嗦一遍这个例子。
1、首先创建一个Person类,并为其增加两个方法

  • (void)name1;

  • (void)sex1;
    2、实现方法

  • (void) name1 {
    NSLog(@"name");
    }

  • (void) sex1 {
    NSLog(@"sex")
    }
    3、实例化对象,并调用方法

Person*person = [[Personalloc]init];
[person name1];
[person sex1];
以上三部很简单,相比大家都能看的懂。而我们最终的目标是

person.name(@"Jason").sex(@"男");
首先我们要实现

[[person name] sex];
实现这个目标很简单,只需要调用[person name]的时候返回一个Person对象就可以了,下面我们来修改代码

  • (Person *)name2;
    • (Person *)sex2;
  • (Person *)name2 {
    NSLog(@"name");
    return self;
    }
  • (Person *)sex2 {
    NSLog(@"sex");
    return self;
    }
    这样就可以实现了,

[[person name2] sex2];
这离我们的最终目标还有一段距离。
先拆分下目标,先实现

[[person name](@"Jason") sex](@"男"); //这个是不是和我们最终的目标很像,只需把中括号换成(.)就可以了

person.name(@"Jason").sex(@"男");

我们都知道OC里面调用方法使用的是[obj func],向一个方法发送一条消息。而没有obj.func(param)的形式,要想实现这个,我们自然而然的会想到OC里面的block,只有block才是以()的方式调用的。
1、我们可以返回一个block,然后使用()去掉用。
2、那么我们要如何实现连续调用呢?我们再分析,要调用一个类的实例方法,必须由这个类的实例对象才能调用,如[[person name] sex]; 我们之所以可以连续使用[ ], 是因为我们返回了一个该实例对象。如果在返回的block里面返回一个实例对象不就可以连续调用了吗,而block正好也能返回一个对象。下面我们再改写代码。

//返回一个block,而block的返回值是一个Person对象

  • (Person * (^)())name3;
  • (Person * (^)())sex3;
  • (Person * (^)())name3 {
    //可以直接返回一个block
    return ^Person *(){
    return self;
    };
    }
  • (Person * (^)())sex3 {
    //也可以定义一个block,接收返回的block,再把block返回
    //等号右边的Person *()可以省略不写,Person *省略不写的原因是返回值本身可以不写,()可以省略不写的原因是block无参数时可以省略()
    Person *(^block)() = ^Person *(){
    return self;
    };
    return block;
    }
    此时我们调用方法

person name3 sex3;
看到如此的写法是不是很奇怪, OC里面调用方法没有这样写的呀,不要着急,我们一步一步分解。

[person name3]
这一步大家都很熟悉吧,我们在前面讲过,name3方法返回的是一个block,我们打印下这个返回值,看看到底是个什么鬼?

NSLog(@"%@", [person name3]);
//<NSMallocBlock: 0x7fa7714193c0>
打印结果告诉我们,返回值是一个block

//这种写法就相当于我们去调用了一个block,前面说过,只有block才会有()的这种语
//还记得前面讲的定时炸弹吗,当执行完[person name3]这句代码的时候,我们就找到了那个炸弹,再执行()的时候,我们就引爆了炸弹。
person name3
前面说过,block也是有返回值的,我们同样打印下block的返回值

NSLog(@"%@", person name3);
<Person: 0x7fd9e9daf980> //返回值是一个对象,很关键
接下来我们换一种写法来理解这句代码,把这句代码分成两步。

//1.声明一个返回值是Person类型, 无参数的block,用于接收返回值
Person * (^returnBlock)() = [person name3];
NSLog(@"%@", [person name3]); //<NSMallocBlock: 0x7f93bfc105a0>
NSLog(@"%@", returnBlock); //<NSMallocBlock: 0x7f93bfcb7a00>
//2.调用block
returnBlock(); //注意此处返回的是一个Person对象, 这是我们实现链式编程的关键
NSLog(@"%@", returnBlock()); //<Person: 0x7fd9e9daf980>
上面的写法是不是容易理解一点呢,首先声明一个返回值是Person类型, 无参数的block,用于接收[person name3]的返回值, 此时我们找到了我们先前已经存好的block(炸弹),然后再去调用block(引爆炸弹)
下面我们再来看之前的代码

[[person name3]() sex3]();

//这一步操作分解之后就是这四步, 此处也能看出,链式编程能提高开发效率和提高代码的可读性
Person * (^returnNameBlock)() = [person name3];
Person *personName = returnNameBlock();
Person * (^returnSexBlock)() = [personName sex3];
Person *personSex = returnSexBlock();
此时离我们最终实现的效果的前一步还差一点,就是没有参数,我们再改写代码,加上参数,实现下面的效果

person name sex;
改写

// 函数的返回值是一个Block,Block的返回值是当前对象,Block有一个参数

  • (Person * (^)(NSString *name))name4; //设置参数
  • (Person * (^)(NSString *sex))sex4;
  • (Person * (^)(NSString *name))name4 {
    // 方法的返回是一个”有参有返回值的Block“
    return ^Person *(NSString *name){
    NSLog(@"%@", name);
    // block的返回值是当前对象
    return self;
    };
    }
  • (Person * (^)(NSString *sex))sex4 {
    return ^Person *(NSString *sex) {
    NSLog(@"%@", sex);
    return self;
    };
    }
    //调用

//(@"Jason")这个参数是block的参数,并且是block作为返回值的参数,在文章的开头已经说过,block的返回值参数用于从外向内返回结果,这就是为什么我们在外面传入参数(@"Jason"),而在函数内部会打印我们传入的参数,这点不要搞错。-->>解释文章开头第二个问题
person name4 sex4;
OK,经历九九八十一难,我们终于到达了天竺,离求取真经只差一步了
我们要的结果是

person.name(@"Jason").sex(@"男");
而我们现在的结果和这个目标只差一步了,是不是感觉有点小激动呢。
还是文章开头的第一个问题-->> 为什么可以使用.语法来调用方法,而不是使用OC里面的[ ]。
首先我们要知道OC里面的属性声明默认是私有的,外部是不可以直接访问的,而setter个getter方法是可以间接访问属性的。其实在使用self.propert语法时,不是直接访问属性,而是隐士的调用了setter或者getter方法来访问属性的,在编译与运行期间,并不关心你是否在真正的在获取一个属性。要实现使用.点语法调用方法,你的方法,必须有一个返回值,并且无参数。这样才符合getter方法的书写规范,而我们最终使用的方法整好符合这种规范。所以,你就可以直接使用 person.name(@"Jason").sex(@"男");来调用方法了。

最终我们实现了

person.name(@"Jason").sex(@"男");
你可以尽情的 . 下去了

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

推荐阅读更多精彩内容