Objective-C程序员Ios@IONIC

iOS函数编程和链式编程(使用block仿Masnory实现)

2016-08-08  本文已影响821人  长若执念

实在不好意思,题目起的太大了,这里只是对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);
    }];
    

我们想要实现的效果是:

  1. 我们在使用过程中需要 先执行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);
各位朋友:源码在demo
上一篇下一篇

猜你喜欢

热点阅读