实在不好意思,题目起的太大了,这里只是对Masnory的实现仿照写一个最简单的demo.把实现思路简单阐述一下,共同进步
各位朋友:源码在demo,可以去看看.
在Masonry中,实现是这样写的:
UIView *v = [[UIImageView alloc]init];
v.backgroundColor = [UIColor redColor];
[self.view addSubview:v];
//使用 Masonry 设置
[v mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(self.view).offset(200);
make.bottom.mas_equalTo(self.view).offset(-200);
make.left.mas_equalTo(self.view).offset(100);
make.right.mas_equalTo(self.view).offset(-100);
}];
我们想要实现的效果是:
- 我们在使用过程中需要 先执行A方法,再执行B方法,或者先执行B方法,再执行A方法,连写在一起,就是 链式编程
[[某实例对象 A方法] B方法];
或者是:
[[某实例对象 B方法] A方法];
2.在OC中 调用方法都是使用 中括号'[]', 使用小括号'()'的在OC 中是 block,调用block时候用,函数编程
//调用block
block();
//最后实现的效果是:
某实例对象.A方法().B方法();
或者是:
某实例对象.B方法().A方法();
我们一步一步来:
创建一个Person类,自己实现
1>我们先来说实现链式编程
思考: 想要实现链式编程,就是需要 某个实例对象,调用了某个方法,返回的还是这个实例对象本身,这样就能继续调用其他的方法了
在Person.h里:
// 链式语法. -->就是连续调用, [[person run] eat],这种.或是[[person eat] run]这种.需要返回值是它本身
-(Person *)run1;
-(Person *)eat1;
在Person.m里:
//下面返回的是其本身,这样就能 使用链式语法,返回还是器本身,就能再继续调用其他的
-(Person *)run1 {
NSLog(@"%s",__FUNCTION__);
return self;
}
-(Person *)eat1 {
NSLog(@"%s",__FUNCTION__);
return self;
}
在ViewController.m里
//1 >链式编程,使用链式语法
[[person run1] eat1]; //可以这样写
[[person eat1] run1]; //也可以调换顺序,这样写
2 >我们现在来实现函数编程,实现person.eat2()
思考: 想要使用函数编程语法, 就是想办法使用小括号'()'. 在OC中,只有调用block的时候,才会使用'()',所以我们要使得run2这个方法的返回值是block.
在Person.h里:
//函数编程 调用方法使用() 小括号
-(void(^)())run2;
在Person.m里:
-(void (^)())run2 {
//我们要返回的函数是一个block,在外面才能调用 person.run2(),这样写
void (^runBlock)() = ^{
NSLog(@"run2");
};
return runBlock;
}
在ViewController.m里
//2 >函数式编程:
person.run2();
3 > 但是 不能继续 person.run3().eat3.
思考:1 > 需要使得第一个方法返回值也是Person,就是本事,self,才能在函数编程的继承上,进行链式编程
2> 实现函数编程基础上的链式编程,需要方法 run3 的返回值是一个block,实现函数编程,在block的内部返回一个Person,实现链式编程
在Person.h里:
// 在使用函数编程编程的 基础上使用 链式编程,需要使得返回值是 本事
-(Person *(^)())run3;
-(Person *(^)())eat3;
在Person.m里:
//3.1 实现函数编程基础上的链式编程,需要方法 run3 的返回值是一个block,实现函数编程,在block的内部返回一个Person,实现链式编程
-(Person *(^)())run3 {
Person *(^runBlock)() = ^{
NSLog(@"--run3");
return self;
};
return runBlock;
}
// 3.2 我们把3.1 内部的实现再写成一步
-(Person *(^)())eat3 {
return ^{
NSLog(@"-eat3");
return self;
};
}
在ViewController.m里
person.run3().eat3(); //可以这样 先跑后吃
person.eat3().run3(); //也可以这样,先吃后跑
4 > 但是还是不能像Masnory那样有参数,我们再改造.
在Person.h里:
//Person *(^)(double) --> Person *是block的返回值. (double)是参数
-(Person *(^)(double))run4;
-(Person *(^)(NSString *))eat4;
在Person.m里:
// 4 我们需要使得block带参数,这样才能有跟Masnory那样 equalTo(self).offset(20);的效果
-(Person *(^)(double))run4 {
//*** '大的返回值'是 这个 run4的返回值. '小的返回值'-->'内部的返回值'是run4的返回值那个block的返回值
return ^(double distance){
NSLog(@"run4,%f",distance);
return self;
};
}
-(Person *(^)(NSString *))eat4 {
return ^(NSString * food){
NSLog(@"eat4 %@",food);
return self;
};
}
在ViewController.m里
person.run4(100).eat4(@"面包");
person.eat4(@"大米饭").run4(300);
但是,发现这样写block,实在是一种痛苦,还是使用typedef来实现吧:(这就是所谓的先苦后甜吧)
在Person.h里:
@class Person;
typedef Person *(^myRunblock)(double distance); //这个distance,可以省略不写
typedef Person *(^myEatblock)(NSString *);
....
//5, 使用起别名的block,进行函数编程和链式编程
-(myRunblock)run5;
-(myEatblock)eat5;
在Person.m里:
// 使用起别名的block 再进行 函数编程和链式编程,比较方便
-(myRunblock)run5 {
return ^(double distance){
NSLog(@"run5 %f",distance);
return self;
};
}
-(myEatblock)eat5 {
return ^(NSString *food){
NSLog(@"eat5 %@",food);
return self;
};
}
在ViewController.m里
//5 但是我们都是在person手写block的,这样早控制器中使用的时候函数编程的时候,没有提示,我们使用 tydefe个block起别名试试,再说
person.run5(20).eat5(@"馒头");
person.eat5(@"西瓜").run5(10);