iOS 移动端生成工具开发
一、准备工作
编译环境 xcode
用于生成冗余架构代码, 实现生成零耦合架构
二、程序实现
上个月的一篇移动端面向文档开发一文久违的被编辑推荐到了首页, 也引来了饿了么大神的关注, 虽然最后实力不济未被录用, 但也指明了我前进的方向. 从4月到现在从一个想法到一步步的实现, 感觉自己还是有充足的长进的, 今天我们继续来完善这个项目.
之前有写过一个python脚本的生成工具, 通过读取json文件进行代码的生成, 实际操作中部分使用者反映, json文件的可读性不是很好(明显是不熟悉json语法导致的), 以及需要生成多平台代码, 所以python并不是很熟练的我, 考虑再三还是写一个oc项目一劳永逸. 本文会涉及到一些平时开发并不会特别关注的知识点, 以及该生成工具的代码设计和使用方法.
选择项目类型
第一个脑中闪现的想法就是使用Command Line Tool命令行工具了, 不就是代码生成吗, 还要开启模拟器? 这不是逗咩...
但我们需要读取Template模板文件, 由于模板文件是不可编译的文件, 所以我们并不能直接将其拖入项目中来, 然后我想那就通过相对路径的方法来读取文件吧, 可惜的是我找了一圈都没有获取当前路径的api, 只有sandbox, 沙盒...
我想命令行工具还有沙盒这玩意? 好吧, 我试试通过Bundle进行获取吧, 试了很久获取到的都是null, 无语... 到Stack Overflow上一问, 命令行工具不支持自制Bundle的读取, 好吧, 我认了. 但我感觉这只是一个链接的问题, 应该是可以读取的, 可惜找不到可执行的方法, 无奈只有放弃.
被迫我们只能够选择Single View Application了, 只是万般无奈啊, 好吧, 对世事的妥协不也是生活中的一部分嘛...
选择配置文件
在配置文件上的选择其实比较简单, 既然是oc的项目, 选择读取最为简单的plist是最好的选择. 同时也比较容易配置.
进行了一些简单的配置, 这部分不是很清晰的同学可以前往 http://www.jianshu.com/p/47d565bf200e 进行了解.
配置完plist后我们将之前的模板一起放入bundle并引入工程.
知识点: 放入bundle的文件并不会进行编译, 仅作为资源文件存储.
选择设计模式
对于设计模式来说, 确实是看过不少相关类型的书籍, 一些常用的设计模式也是手到擒来, 这不, 对于代码生成工具, 立马能够想到生成器模式, 哈哈, 是工厂模式和装饰模式.
其实对于这些设计模式的命名其实感觉挺误导人的, 什么责任链咯, 原型什么的, 其实看一遍代码就懂得东西被吹的神神道道, 也是醉了.
通过设计模式的选择后我们创建了SQBuilder
和SQFileParser
, 前者为工厂模式, 后者为装饰模式.
@interface SQBuilder : NSObject
@property (nonatomic,copy) NSString * user;
@property (nonatomic,copy) NSString * prefix;
@property (nonatomic,copy) NSString * module;
@property (nonatomic,strong) NSDictionary * parameter;
@property (nonatomic,strong) NSDictionary * dataList;
@property (nonatomic,strong) NSArray * actionList;
+ (void)runWithFileParser:(NSDictionary *)config success:(void (^)())success failure:(void (^)())failure;
- (void)build;
@end
+ (SQBuilder *)builderWithType:(SQBuilderType)builderType {
switch (builderType) {
case SQBuilderTypeiOS:
return [SQBuilder_iOS new];
break;
case SQBuilderTypeAndroid:
return [SQBuilder_Android new];
break;
case SQBuilderTypeNone:
return [SQBuilder new];
break;
default:
break;
}
}
SQBuilder的头文件暴露了和plist中需要配置的属性以及加载SQFileParser文件解析类的方法. 通过工厂模式可以分配创建不同的类.
@interface SQFileParser : NSObject
+ (NSDictionary *)parser_plist_r;
+ (void)parser_rw:(NSString *)path code:(NSString *)code filename:(NSString *)filename header:(NSString *)header parameter:(NSMutableArray *)parameter;
@end
[SQBuilder runWithFileParser:[SQFileParser parser_plist_r] success:^{
title = @"Build Finished"; message = @"please view the floder on the desktop";
} failure:^{
title = @"Build Error!!!"; message = @"please enter the right builder type!!";
}];
SQFileParser的头文件暴露了读取不同文件类型的接口, 后续读取Excel表格类型仅需添加新的类型接口即可.
创建文件夹 Api
NSFileManager * manager = [NSFileManager defaultManager];
NSString * path = [NSString stringWithFormat:@"/Users/%@/Desktop/%@", self.user, self.module];
[manager createDirectoryAtPath:path withIntermediateDirectories:NO attributes:nil error:nil];
oc中创建文件夹的方式, 能找到的就只有这个了, 而且只能读取绝对路径, 但又不能读取当前文件路径, mac机的user每台机器都不一样, 真是坑啊, 像文件读写这种东西还是python写最为稳妥.
SQFileParser 代码分析
+ (NSDictionary *)parser_plist_r {
NSBundle * bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"builder.bundle" ofType:nil]];
return [NSDictionary dictionaryWithContentsOfFile:[bundle pathForResource:@"config/config.plist" ofType:nil]];
}
通过子bundle进行读取/config.plist配置文件, 知识点: 当读取bundle深层结构时需要添加文件路径.
+ (NSString *)parser_r:(NSString *)filename code:(NSString *)code {
NSBundle * bundle = [NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"builder.bundle" ofType:nil]];
return [NSMutableString stringWithContentsOfFile:[bundle pathForResource:[NSString stringWithFormat:@"template/%@/%@", code, filename] ofType:nil] encoding:NSUTF8StringEncoding error:nil];
}
Templete文件的读取, 和上面的读取plist相同, 并没有什么不同之处.
static NSString * code;
+ (NSString *)replaceThougth:(NSString *)templete parameter:(NSMutableArray *)parameter {
__block NSString * temp = templete;
[[parameter firstObject] enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
temp = [templete stringByReplacingOccurrencesOfString:key withString:obj];
}];
[parameter removeObjectAtIndex:0];
if (parameter.count) {
[SQFileParser replaceThougth:temp parameter:parameter];
} else {
code = temp;
}
return code;
}
写入新文件, 这个就要好好讲讲了, NSString的stringByReplacingOccurrencesOfString
方法是会返回一个新的更改后的字符串但并不会改变原指针. 但如果需要替换很多处的话就需要链式调用多次, 真是丑, 一个字概括了所有的观点, 所以我在想有什么方法能够避免这个问题呢? 马上想的就是上述递归调用的方法啦, 哈哈.
+ (void)parser_rw:(NSString *)path code:(NSString *)code filename:(NSString *)filename header:(NSString *)header parameter:(NSMutableArray *)parameter {
NSString * arch = [[filename componentsSeparatedByString:@"."]firstObject];
NSString * suffix = [[filename componentsSeparatedByString:@"."]lastObject];
NSString * filename_r = [NSString stringWithFormat:@"%@Template.%@", arch,suffix];
NSString * filename_w = [NSString stringWithFormat:@"%@/%@%@.%@", path,header,arch,suffix];
NSString * template = [SQFileParser parser_r:filename_r code:[code lowercaseString]];
[[SQFileParser replaceThougth:template parameter:parameter] writeToFile:filename_w atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
这个方法是读写一体的, 根据拿到的配置参数, 拼接出输入文件名和输出文件名, 并进行文件的读取和写入.
SQBuilder
这个其实就没什么好讲的了, 自己去看代码即可, 仅是读取配置参数并动态生成方法的逻辑代码了.
如何使用?
打开终端输入pwd获取user信息,并填入plist配置文件, 并输入其他参数, 进行Run
即可将代码生成至桌面. 以后开发的时候只需要关注View层, 其他的都不需要操心啦~~
三、运行效果
四、其他补充
项目代码结构图
就是上面的使用截图,另外也这里也补充项目截图:
iOS 移动端生成工具开发
注:本文著作权归作者,由demo大师代发,拒绝转载,转载需要作者授权
iOS 移动端生成工具开发的更多相关文章
- H5类似易企秀/编辑器/页面制作/开发/生成工具/软件/源码/授权
代码地址如下:http://www.demodashi.com/demo/14960.html 项目简介 H5DS (HTML5 Design software) 这是一款基于WEB的 H5制作工具. ...
- ChaosTool,iOS添加垃圾代码工具,代码混淆工具,代码生成器,史上最好用的垃圾代码添加工具,自己开发的小工具
最近在H5游戏项目中需要添加垃圾代码作混淆,提高过审机率.手动添加太费时费力,在网上并没有找到合适的比较好的工具,就自己动手写了一个垃圾代码添加工具,命名为ChaosTool. 扣扣交流群:81171 ...
- Web 开发人员必备的随机 JSON 数据生成工具
在 Web 开发中,经常会需要一些测试数据来测试接口或者功能时候正确.JSON Generator 就是这样一款生成随机 JSON 数据的在线工具,Web 开发人员必备,记得收藏和分享啊. 您可能感兴 ...
- 微信开发中access_token,js_ticket,时间戳,签名生成工具
Access_token生成工具 工具地址:https://mp.weixin.qq.com/debug 这个工具主要用来验证和生成微信公众号access_token,主要有正确的app_id和app ...
- 基于 React 开发了一个 Markdown 文档站点生成工具
Create React Doc 是一个使用 React 的 markdown 文档站点生成工具.就像 create-react-app 一样,开发者可以使用 Create React Doc 来开发 ...
- 移动端使用rem同时适应安卓ios手机原理解析,移动端响应式开发
rem单位大家可能已经很熟悉,rem是随着html的字体大小来显示代表宽度的方法,我们怎样进行移动端响应式开发呢 浏览器默认的字体大小为16px 及1rem 等于 16px 如果我们想要使1rem等于 ...
- iOS:崩溃统计工具Crashlytics的使用
一.介绍 随着苹果在世界火热起来,移动端app的开发如火如荼,同时催生出了一批对app进行统计的开发工具,诸如:国内的友盟统计.国外的Flurry移动端统计.国外的Crashlytics统计等,Cra ...
- iOS应用内付费(IAP)开发步骤列表
iOS应用内付费(IAP)开发步骤列表 前两天和服务端同事一起,完成了应用内付费(以下简称IAP, In app purchase)的开发工作.步骤繁多,在此把开发步骤列表整理如下.因为只是步骤列表, ...
- python测试框架&&数据生成&&工具最全资源汇总
xUnit frameworks 单元测试框架frameworks 框架unittest - python自带的单元测试库,开箱即用unittest2 - 加强版的单元测试框架,适用于Python 2 ...
随机推荐
- BZOJ 2809 [Apio2012]dispatching(斜堆+树形DP)
[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2809 [题目大意] 给出一棵树,求出每个点有个权值,和一个乘算值,请选取一棵子树, 并 ...
- 【序列莫队+树状数组】BZOJ3289-Mato的文件管理
[题目大意] 一共有n份,每份有一个大小和一个编号.Mato每天随机选一个区间[l,r],拷贝出来(即对原序列不影响),给它们排序,并且每次只能交换相邻两份文件.问每天最少交换几次? [思路] 显然, ...
- Apache静态编译与动态编译详解
Apache拥有4层结构,从核心到外层的module.而外层的module可以用通过静态和动态两种方式与Apache共同工作.这也就引入下文的“动态”和“静态”两种编译安装方式: 静态编译: 编译的时 ...
- django--02 模板的使用
参考链接:https://www.w3cschool.cn/django/django-template.html 1.新建模板目录 templates 2.在setting文件中注册模板 修改 T ...
- java多线程加锁是对谁加锁?
1.java多线程加锁是对谁加锁? 答:当然是对共享资源加锁啊,对谁进行访问修改,就对象进行加锁.以便使多线程按序访问此共享对象 比如: 在具体的Java代码中需要完成一下两个操作:把竞争访问的资源类 ...
- QJSON封装好的序列和还原方法
QJSON封装好的序列和还原方法 {*******************************************************}{ }{ QJSON与数据集互转 }{ }{ 版权所 ...
- TWinHTTP
TWinHTTP USES SynCrtSock procedure hget(const url: string; var ResponseCode: Integer; var ResponseHe ...
- c#中的??运算符
注意啦,c#中的??运算符是和?:运算符是不同的,这两者是有区别的. ??运算符称为null合并运算符,用于定义null值的类型和引用类型的默认值. 只当运算符的左操作数不为 null,此运算符将返回 ...
- extern用法
Extern用法 用例子给你示范 // 1.cpp ; // 2.cpp 注意没有包含1.cpp #include <iostream> using namespace std; exte ...
- Android获取wifi MAC,关闭的wifi不能获取
最近一直在尝试着在Android上通过ndk用C++获取本机MAC地址,但是用ioctl(SIOCGIFHWADDR)时,一直返回值小于0,即获取不到接口信息.刚开始我以为是自己漏掉了哪些访问权限,所 ...