项目github
出发点今天工作中写了一个工具类,在.m中完成所有功能后,发觉把所有接口从.m中拷贝到.h中声明,好麻烦啊,所以就考虑写个命令行工具来做这些工作。
想要达到的结果我们设计这个小工具,在终端中直接运行,传入一个.m文件路径参数,输出其中所有的方法名。
input:> fti PWfileController.m output:- (Nsstring *)bytesToAvaiUnit:(long long)bytes;- (long long) fileSizeAtPath:(Nsstring*) filePath;- (long long) folderSizeAtPath:(Nsstring*) folderPath;- (voID) clearFolderAtPath:(Nsstring*) folderPath;- (float)getTotaldiskSpace;- (Nsstring *)getHomeDirectory;开始
第一步新建一个mac的命令行(Command line Tool)项目,这种项目只有一个main.m
文件,内容如下
#import <Foundation/Foundation.h>int main(int argc,const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello,World!"); } return 0;}
这里先分析一下原理,首先.m文件中的C函数方法是不带自动内存池的,所以要在C方法中使用ObjC代码,必须使用@autoreleasepool
大括号括起来,这样才能保证在C方法结束后,栈内存能够释放。
其次,main函数中的argc参数,代表命令行中参数的个数,argv这个char数组,是每个参数的内容。
所以我们首先判断argc的个数,这里要注意,shell中的命令本身占一个参数位,所以没有任何参数的时候,argc应该为1。
if(argc<=1) return 0; //当argc<=1直接退出程序
接着我们要获取命令行输入的第二个参数,也就是.m文件路径
Nsstring* filePath = [[Nsstring alloc] initWithCString:argv[1] enCoding:NSUTF8StringEnCoding];
如果文件不存在,则结束程序
if(![[NSfileManager defaultManager] fileExistsAtPath:filePath]){ NSLog(@"文件不存在"); return 0;}
接着我们在main函数之前声明一个找接口的方法,这个方法要用C语言方法的格式声明
NSArray* findInterface (Nsstring* text);
然后实现它,注意要加@autoreleasepool
NSArray* findInterface (Nsstring* text){ @autoreleasepool { Nsstring *regex = @"-\s?\(.*?\).*?(?=\n|$|\{)"; Nsstring *str = text; NSError *error; NSRegularExpression *regular = [NSRegularExpression regularExpressionWithPattern:regex options:NSRegularExpressionCaseInsensitive error:&error]; // 对str字符串进行匹配 NSArray *matches = [regular matchesInString:str options:0 range:NSMakeRange(0,str.length)]; NSMutableArray* result = [NSMutableArray arrayWithCapacity:matches.count]; // 遍历匹配后的每一条记录 for (NSTextCheckingResult *match in matches) { NSRange range = [match range]; Nsstring *mStr = [str substringWithRange:range]; [result addobject:mStr]; } return [result copy]; }}
这一段正则表达式的搜索没有特别要说明的,关于NSRegularExpression
这个类的正则的用法,比较简单,参考上面代码就行,所以我简单说下正则的匹配规则
-\s?\(.*?\).*?(?=\n|$|\{)
以-
符号开头,在第一个左括号中间有若干空格,然后有若干空格和字符,然后有一个右括号,接下来又是若干个空格和字符,结尾要匹配三个,换行符\n
,字符串结尾$
和左大括号{
这样我们在main方法中读取文件内容,然后调用这个方法即可输出所有的接口名。
Nsstring* s = [[Nsstring alloc] initWithContentsOffile:filePath enCoding:NSUTF8StringEnCoding error:nil];Nsstring* f = [[findInterface(s) componentsJoinedByString:@";\n"] stringByAppendingString:@";"];NSLog(@"result:\n%@",f);
完整的代码请参考 项目github
使用这个项目通过菜单 Product -> Archive 可以发布released版本的运行程序,然后将其拷贝到/usr/local/bin
目录下,即可在terminal中直接使用。
注意我为了方便,把Archive出来的运行程序名,简化为fti
。
类方法匹配,把正则中的-
改为(-|\+)
即可。
换行的方法,可以根据{
来匹配,把(?=\n|$|\{)
改为[^;]*?(?=\{)
。
原理各位自己分析。
因为修改了匹配规则,我们需要对抓取的内容进行一些处理,
在findInterface方法中,我们去掉检索内容的换行符和;
,用stringByReplacingOccurrencesOfString
方法实现
for (NSTextCheckingResult *match in matches) { NSRange range = [match range]; Nsstring *mStr = [str substringWithRange:range]; mStr = [mStr stringByReplacingOccurrencesOfString:@"\n" withString:@""]; mStr = [mStr stringByReplacingOccurrencesOfString:@";" withString:@""]; mStr = format(mStr); //这个方法在下面的内容zh [result addobject:mStr];}
然后我们增加一个format方法,来把多行函数,格式化成标准的一行函数。
Nsstring* format (Nsstring* string){ @autoreleasepool { string = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; NSArray *components = [string componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; components = [components filteredArrayUsingPredicate:[nspredicate predicateWithFormat:@"self <> ''"]]; string = [components componentsJoinedByString:@" "]; return string; }}总结
以上是内存溢出为你收集整理的教你写一个可以找到.m文件所有接口名的命令行工具全部内容,希望文章能够帮你解决教你写一个可以找到.m文件所有接口名的命令行工具所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)