python 代码生成器 oc_iOS 移动端生成工具开发
原標(biāo)題:iOS 移動(dòng)端生成工具開發(fā)
之前有寫過一個(gè)python腳本的生成工具, 通過讀取json文件進(jìn)行代碼的生成, 實(shí)際操作中部分使用者反映, json文件的可讀性不是很好(明顯是不熟悉json語法導(dǎo)致的), 以及需要生成多平臺(tái)代碼, 所以python并不是很熟練的我, 考慮再三還是寫一個(gè)oc項(xiàng)目一勞永逸. 本文會(huì)涉及到一些平時(shí)開發(fā)并不會(huì)特別關(guān)注的知識(shí)點(diǎn), 以及該生成工具的代碼設(shè)計(jì)和使用方法.
選擇項(xiàng)目類型
第一個(gè)腦中閃現(xiàn)的想法就是使用Command Line Tool命令行工具了, 不就是代碼生成嗎, 還要開啟模擬器? 這不是逗咩...
但我們需要讀取Template模板文件, 由于模板文件是不可編譯的文件, 所以我們并不能直接將其拖入項(xiàng)目中來, 然后我想那就通過相對(duì)路徑的方法來讀取文件吧, 可惜的是我找了一圈都沒有獲取當(dāng)前路徑的api, 只有sandbox, 沙盒...
我想命令行工具還有沙盒這玩意? 好吧, 我試試通過Bundle進(jìn)行獲取吧, 試了很久獲取到的都是null, 無語... 到Stack Overflow上一問, 命令行工具不支持自制Bundle的讀取, 好吧, 我認(rèn)了. 但我感覺這只是一個(gè)鏈接的問題, 應(yīng)該是可以讀取的, 可惜找不到可執(zhí)行的方法, 無奈只有放棄.
被迫我們只能夠選擇Single View Application了, 只是萬般無奈啊, 好吧, 對(duì)世事的妥協(xié)不也是生活中的一部分嘛...
選擇配置文件
在配置文件上的選擇其實(shí)比較簡(jiǎn)單, 既然是oc的項(xiàng)目, 選擇讀取最為簡(jiǎn)單的plist是最好的選擇. 同時(shí)也比較容易配置.
進(jìn)行了一些簡(jiǎn)單的配置, 這部分不是很清晰的同學(xué)可以前往 http://www.jianshu.com/p/47d565bf200e 進(jìn)行了解.
配置完plist后我們將之前的模板一起放入bundle并引入工程.
知識(shí)點(diǎn): 放入bundle的文件并不會(huì)進(jìn)行編譯, 僅作為資源文件存儲(chǔ).
選擇設(shè)計(jì)模式
對(duì)于設(shè)計(jì)模式來說, 確實(shí)是看過不少相關(guān)類型的書籍, 一些常用的設(shè)計(jì)模式也是手到擒來, 這不, 對(duì)于代碼生成工具, 立馬能夠想到生成器模式, 哈哈, 是工廠模式和裝飾模式.
其實(shí)對(duì)于這些設(shè)計(jì)模式的命名其實(shí)感覺挺誤導(dǎo)人的, 什么責(zé)任鏈咯, 原型什么的, 其實(shí)看一遍代碼就懂得東西被吹的神神道道, 也是醉了.
通過設(shè)計(jì)模式的選擇后我們創(chuàng)建了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文件解析類的方法. 通過工廠模式可以分配創(chuàng)建不同的類.
@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的頭文件暴露了讀取不同文件類型的接口, 后續(xù)讀取Excel表格類型僅需添加新的類型接口即可.
創(chuàng)建文件夾 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中創(chuàng)建文件夾的方式, 能找到的就只有這個(gè)了, 而且只能讀取絕對(duì)路徑, 但又不能讀取當(dāng)前文件路徑, mac機(jī)的user每臺(tái)機(jī)器都不一樣, 真是坑啊, 像文件讀寫這種東西還是python寫最為穩(wěn)妥.
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進(jìn)行讀取/config.plist配置文件, 知識(shí)點(diǎn): 當(dāng)讀取bundle深層結(jié)構(gòu)時(shí)需要添加文件路徑.
+ (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;
}
寫入新文件, 這個(gè)就要好好講講了, NSString的stringByReplacingOccurrencesOfString方法是會(huì)返回一個(gè)新的更改后的字符串但并不會(huì)改變?cè)羔? 但如果需要替換很多處的話就需要鏈?zhǔn)秸{(diào)用多次, 真是丑, 一個(gè)字概括了所有的觀點(diǎn), 所以我在想有什么方法能夠避免這個(gè)問題呢? 馬上想的就是上述遞歸調(diào)用的方法啦, 哈哈.
+ (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];
}
這個(gè)方法是讀寫一體的, 根據(jù)拿到的配置參數(shù), 拼接出輸入文件名和輸出文件名, 并進(jìn)行文件的讀取和寫入.
SQBuilder
這個(gè)其實(shí)就沒什么好講的了, 自己去看代碼即可, 僅是讀取配置參數(shù)并動(dòng)態(tài)生成方法的邏輯代碼了.
如何使用?
打開終端輸入pwd獲取user信息,并填入plist配置文件, 并輸入其他參數(shù), 進(jìn)行Run即可將代碼生成至桌面. 以后開發(fā)的時(shí)候只需要關(guān)注View層, 其他的都不需要操心啦~~
具體說明可以下載SQTemplate來進(jìn)行共同探討.(https://github.com/coderZsq/coderZsq.project.oc)
鏈接:http://www.jianshu.com/p/cb36b36f90dd
iOS開發(fā)整理發(fā)布,轉(zhuǎn)載請(qǐng)聯(lián)系作者授權(quán)返回搜狐,查看更多
責(zé)任編輯:
總結(jié)
以上是生活随笔為你收集整理的python 代码生成器 oc_iOS 移动端生成工具开发的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 辽宁舰过海峡 歼-11护卫轰-6K绕飞
- 下一篇: 信息化建设规划_苏交集团施工企业信息化建