iOS中如何做个代码生成器减少重复劳动?

代码生成器

前言

最近在为一个新项目搭建项目框架。网络层在iOS项目中的地位不言而喻,一个不可或缺的部分,它负责api请求,上传下载等通信功能。之前也曾在AFNetworking的基础上封装过网络库。但在发现了猿题库的网络库后,发现它提供了很强大的功能,比如链式请求,断点上传等功能,这次新项目决定尝试下。猿题库的地址:https://github.com/yuantiku/YTKNetwork
YTKNetwork虽然功能强大,但在使用过程中发现它的代码量比较大,到处是重复地复制粘贴。因为它是将每个网络请求都封装起来,即一个api对应一个网络请求类,而且将请求参数也作为成员变量封装起来。使用起来很不便。
最后尝试使用代码生成器的方式,配置好请求的各项参数,根据模板自动自成网络api类文件。
以下是具体实现方法和源码实例,也借此实例说明一下iOS中代码生成器的基本使用方法。

MGTemplateEngine

MGTemplateEngine是mac平台下的一个代码生成器工具,根据模板和数据自动生成结果。它的使用很简单,语法比较灵活。

NSString *name = @"zcj"

//Hellow {{ name }}!
//打印结果:Hellow zcj!

当然了,MGTemplateEngine也支持循环和条件判断,如下所示:

NSArray *arr = [NSArray arrayWithObjects:
                                @"matt", @"iain", @"neil", @"chris", @"steve", nil], @"guys"];

//{% for dude in guys %}
    Current dude is {{ dude | uppercase }}
{% /for %}
//打印结果:Current dude is matt
//Current dude is iain
//Current dude is neil
//Current dude is chris

Is 1 less than 2? {% if 1 < 2 %} Yes! {% else %} No? {% /if %}
//打印结果:Is 1 less than 2? Yes! 

这些是MGTemplateEngine基本的用法,MGTemplateEngine还提供更强大的规则和语法,详细信息请前往官方文档查询,地址:https://github.com/mattgemmell/MGTemplateEngine。

代码生成器

我们看一下YTKNetwork的请求类是什么样的

// RegisterApi.h
#import "YTKRequest.h"

@interface RegisterApi : YTKRequest

- (id)initWithUsername:(NSString *)username password:(NSString *)password;

@end


// RegisterApi.m

#import "RegisterApi.h"

@implementation RegisterApi {
    NSString *_username;
    NSString *_password;
}

- (id)initWithUsername:(NSString *)username password:(NSString *)password {
    self = [super init];
    if (self) {
        _username = username;
        _password = password;
    }
    return self;
}

- (NSString *)requestUrl {
    // “ http://www.yuantiku.com ” 在 YTKNetworkConfig 中设置,这里只填除去域名剩余的网址信息
    return @"/iphone/register";
}

- (YTKRequestMethod)requestMethod {
    return YTKRequestMethodPOST;
}

- (id)requestArgument {
    return @{
        @"username": _username,
        @"password": _password
    };
}

@end

我们发现,这个类的内容格式比较固定,只有类名,成员变量名,url和请求类型是不固定的,这样我们就能使用代码生成器制作模板了。
先画个界面,放置一些需要输入的参数,包括类名,成员变量名,url和请求类型。
将用户输入的数据按一定的格式组织起来,放置到字典中。其中请求参数的数据结构是以键值对的格式放到数组中,具体请看源码。

    // Set up some variables for this specific template.
    NSDictionary *variables = [NSDictionary dictionaryWithObjectsAndKeys:
                               mArr, @"Param",
                               _classNameTF.stringValue, @"ClassName",
                               _urlTF.stringValue, @"Url",
                               [_typeCB objectValueOfSelectedItem], @"MethodType",
                               nil];

下面来做类的模板,这个类基本结构不变,将类名,成员变量名,url和请求类型等几处替换掉成变量形式,成员变量部分要根据输入的数据动态生成,代码如下:

//
//  {{ ClassName }}.m
//  ZCJNetworkCodeGenerateTool
//
//  Created by zcj on 2017/2/24.
//  Copyright © 2017年 zcj. All rights reserved.
//

#import "{{ ClassName }}.h"

@implementation {{ ClassName }} {
{% for p in Param %}
    {{ p.value }} *_{{ p.key }};
{% /for %}
}


- (id)init{% for p in Param %}With{{ p.key | capitalized }}:({{ p.value }} *){{ p.key }} {% /for %}{
    self = [super init];
    if (self) {
        {% for p in Param %}
        _{{ p.key }} = {{ p.key }};
        {% /for %}
    }
    return self;
}

- (NSString *)requestUrl {
    return @"{{ Url }}";
}

- (YTKRequestMethod)requestMethod {
    return {{ MethodType }};
}

- (id)requestArgument {

    return @{ {% for p in Param %}@"{{ p.key }}": _{{ p.key }}{% if [email protected] equalsString p.key %}{% else %}, {% /if %}{% /for %}};
}
@end

总结

最后放上实例源码:https://github.com/superzcj/ZCJTemplateTool
代码生成器的实现还是比较简单的,了解一下MGTemplateEngine的语法和规则,很容易写出自己的代码生成器。利用MGTemplateEngine之类的工具可以帮助我们简化了大部分的重复性工作,节省大家的时间。
掌握了代码生成器的基本使用,我们就可以在遇到类似重复性任务场景,做出自己的自动化处理方法。
如果觉得我的这篇文章对你有帮助,请在下方点个赞支持一下,谢谢!

你可能感兴趣的:(iOS中如何做个代码生成器减少重复劳动?)