美文网首页
[iOS] 类似于Masonry中的链式编程

[iOS] 类似于Masonry中的链式编程

作者: 沉江小鱼 | 来源:发表于2021-07-11 19:22 被阅读0次

前言:之前记得有看过链式编程的实现,主要就是用 block 实现的,现在特地再记录一下。

1. 简介

在了解链式编程的时候,不得不提起 Masonry 这个框架了,代码如下:

[view mas_makeConstraints:^(MASConstraintMaker *make) {
      make.top.left.bottom.and.right.equalTo(@(0)); // 链式调用
}];

当时看到这种写法的时候,很惊叹,毕竟和 OC 中常见的方法调用大相径庭,但是写起来很简单,看起来很方便,所以我们可以学习一下这种方式,应用到自己的项目中,提高代码的阅读性。

2. 实现

2.1 链式调用的初步实现

我们创建一个 Student 类,将它改造为链式调用,初始的代码如下:

@interface Student : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (void)sayName;
- (void)sayAge;

@end

@implementation Student

- (void)sayName{
    NSLog(@"name is %@", self.name);
}

- (void)sayAge{
    NSLog(@"age is %ld", self.age);
}

@end

在使用时的调用如下:

Student *student = [[Student alloc] init];
student.name = @"张三";
student.age = 22;
    
[student sayName];
[student sayAge];

我们如果要实现连续调用sayNamesayAge方法,那么sayName方法返回值就不能为空,应该为Student对象:

修改 sayName 方法实现为:
- (Student *)sayName{
    NSLog(@"name is %@", self.name);
    return self;
}

这样就可以[[student sayName] sayAge]进行调用了。

但是 Masonry 方法调用是通过. + () 进行调用的,所以对sayAge方法进行修改:

- (void(^)(void))sayAge{
    return ^(){
        NSLog(@"age is %ld", self.age);
    };
}

这样可以实现[student sayName].sayAge()调用了。

我们继续对sayName方法进行修改,让它的调用方式也支持 sayName(),代码如下:

- (Student *(^)(void))sayName{
    return ^(){
        NSLog(@"name is %@", self.name);
        return self;
    };
}

这样就可以实现student.sayName().sayAge(); 链式调用了,主要实现就是方法返回一个 block,block 的返回值为当前对象,这样当链式调用 block的时候,其返回值是当前对象,这样就可以一直链式调用下去了。

2.2 构造方法的实现

主要也是通过 block,将当前实例对象传到外面,在外部进行赋值,代码如下:

- (instancetype)initWithConfig:(void(^)(Student *student))config{
    Student *student = [[Student alloc] init];
    config(student);
    return student;
}


// 构造时使用:
Student *student = [[Student alloc] initWithConfig:^(Student * _Nonnull stu) {
    stu.name = @"张三";
    stu.age = 22;
}];

目前经过上面两个步骤之后,Student 类中的代码如下:

@interface Student : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (instancetype)initWithConfig:(void(^)(Student *student))config;

- (Student *(^)(void))sayName;
- (void(^)(void))sayAge;

@end

@implementation Student

- (instancetype)initWithConfig:(void(^)(Student *student))config{
    Student *student = [[Student alloc] init];
    config(student);
    return student;
}

- (Student *(^)(void))sayName{
    return ^(){
        NSLog(@"name is %@", self.name);
        return self;
    };
}

- (void(^)(void))sayAge{
    return ^(){
        NSLog(@"age is %ld", self.age);
    };
}

@end

调用时:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    Student *student = [[Student alloc] initWithConfig:^(Student * _Nonnull stu) {
        stu.name = @"张三";
        stu.age = 22;
    }];
    student.sayName().sayAge();
}

3. 改进

在上面的实现中,.点语法调用实际上是方法调用,但是我们习惯用点语法对属性进行操作。所以我们应该将 block 声明为属性,然后重写 getter 方法,改进后的 Student 类:

@interface Student : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) NSInteger age;

@property (nonatomic, copy) Student *(^sayName)(void);
@property (nonatomic, copy) Student *(^sayAge)(void);


- (instancetype)initWithConfig:(void(^)(Student *student))config;

@end

@implementation Student

- (instancetype)initWithConfig:(void(^)(Student *student))config{
    Student *student = [[Student alloc] init];
    config(student);
    return student;
}

- (Student *(^)(void))sayName{
    return ^(){
        NSLog(@"name is %@", self.name);
        return self;
    };
}

- (Student * _Nonnull (^)(void))sayAge{
    return ^(){
        NSLog(@"age is %ld", self.age);
        return self;
    };
}

@end

大概就是这么个样子了,上面没有涉及到一些参数的传递,下面的例子中会有补充。

4. 举例

我们继承系统的 UILabel,然后实现一个子类TTLabel,子类的初始化配置就使用链式调用,具体代码如下:

@interface TTLabel : UILabel

@property (nonatomic, copy, readonly) TTLabel *(^setFontColor)(UIColor *color);
@property (nonatomic, copy, readonly) TTLabel *(^setFont)(UIFont *font);
@property (nonatomic, copy, readonly) TTLabel *(^setBgColor)(UIColor* bgColor);
@property (nonatomic, copy, readonly) TTLabel *(^setContent)(NSString *text);

@end

@implementation TTLabel

- (TTLabel * _Nonnull (^)(UIColor * _Nonnull color))setFontColor{
    return ^(UIColor *color){
        self.textColor = color;
        return self;
    };
}

- (TTLabel * _Nonnull (^)(UIFont * _Nonnull font))setFont{
    return ^(UIFont *font){
        self.font = font;
        return self;
    };
}

- (TTLabel * _Nonnull (^)(UIColor * _Nonnull bgColor))setBgColor{
    return ^(UIColor *bgColor){
        self.backgroundColor = bgColor;
        return self;
    };
}

- (TTLabel * _Nonnull (^)(NSString * _Nonnull text))setContent{
    return ^(NSString *text){
        self.text = text;
        return self;
    };
}


@end

调用时:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    TTLabel *label = [[TTLabel alloc] initWithFrame:CGRectMake(100, 100, 300, 50)];
    [self.view addSubview:label];
    label.setContent(@"你好啊").setFont([UIFont systemFontOfSize:20]).setFontColor(UIColor.redColor).setBgColor(UIColor.blueColor);
}

定义属性相比定义方法一个突出的优点就是输入的时候会有输入提示,所以更常用。

对于这种链式调用有了一个了解之后,可以看下 Masonry 中的使用了,不得不赞叹,开源框架的作者真的厉害!!!

相关文章

  • [iOS] 类似于Masonry中的链式编程

    前言:之前记得有看过链式编程的实现,主要就是用 block 实现的,现在特地再记录一下。 1. 简介 在了解链式编...

  • iOS开发Masonry框架源码解析

    iOS开发Masonry框架源码解析 前言:这个框架编程思想主要包括链式编程 这是一个iOS在控件布局中的轻量级框...

  • iOS链式编程思路

    iOS中链式编程最有名的莫过于Masonry了,以前就觉得Masonry的语法很好看,简单清楚明了,担得起“优雅”...

  • iOS链式编程之block作为返回值使用

    链式编程近几年算是一个比较火的概念了,使用过masonry的人应该也比较熟悉链式编程这个概念,那么,在iOS中是怎...

  • 一探 mas_updateConstraints 究竟

    原文 : 与佳期的个人博客(gonghonglou.com) Masonry 的链式编程对 iOS UI 添加约束...

  • 链式编程

    链式编程 实现一个类似于 Masonry 的链式编程,加法。 第一步 我们需要一个返回值是 Int 的方法,入参应...

  • iOS链式编程的实现方案

    在iOS中,Masonry自动布局库是典型的链式与函数式编程的集中体现。基于函数式编程范式的思想,包装组装对应的功...

  • 链式编程

    最近有时间看了下Masonry的实现原理,大家都知道Masonry就是经典的链式编程思想 链式编程小练习 1.创建...

  • 简单的链式编程(iOS)

    1.链式编程思想 最初接触Masonry框架的时候还不知道什么链式编程,最初的感觉就是Masonry使用起来很简洁...

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

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

网友评论

      本文标题:[iOS] 类似于Masonry中的链式编程

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