检测无用的方法

1.所有的方法

通过buildSetting->LinkMap设为yes且设map路径生成文件。

2.真正使用的方法:

通过otool反编译出selrefs段,如:otool -v -s __DATA __objc_selrefs /Users/a58/Library/Developer/Xcode/DerivedData/bangjob-gwroieegkblzmfbtvtdfeztswqdc/Build/Products/Debug-iphoneos/bangjob.app/bangjob >> bang_sel生成文件。执行文件路径指的是app包里的macho文件。

3.无用的方法 = 所有方法 - 真正的方法

所有代码如下:

/*
 *  所有方法-真正的方法=无用的方法
 */
- (void)testMinus {
    NSMutableSet *set1 = [self testFile];
    NSMutableSet *set2 = [self testOtoolBangFile];
    NSLog(@"所有方法count:%ld, 真正使用的方法count:%ld", set1.count, set2.count);
    NSLog(@"正在相减...");
    [set1 minusSet:set2];
    NSLog(@"无用方法的count:%ld, 包含set方法", set1.count);

    NSMutableSet *containSetterSet = [NSMutableSet set];
    for (NSString *sel in set1) {
        if([sel hasPrefix:@"set"]) {
            [containSetterSet addObject:sel];
        }
    }
    
    NSLog(@"去除set方法 %ld个", containSetterSet.count);
    [set1 minusSet:containSetterSet];
    
    NSLog(@"最终无用方法的count:%ld个", set1.count);
    [[set1 allObjects] writeToFile:@"/Users/a58/noUse-sel" atomically:YES];
    NSLog(@"还是不行,包含getter方法!平时直接用_变量并不调getter方法;并且包含第三方的无用方法");
}

/*
 *  真正使用的方法。
 *  通过命令otool -v -s __DATA __objc_selrefs /Users/a58/Library/Developer/Xcode/DerivedData/bangjob-gwroieegkblzmfbtvtdfeztswqdc/Build/Products/Debug-iphoneos/bangjob.app/bangjob >> bang_sel 生成文件
 */
- (NSMutableSet *)testOtoolBangFile {
    
    NSError *error;
    NSString *content = [NSString stringWithContentsOfFile:@"/Users/a58/bang_sel" encoding:NSASCIIStringEncoding error:&error];
    NSString *patternStr = [NSString stringWithFormat:@"__objc_methname:([0-9a-zA-Z_:]+)\\n"];
    NSRegularExpression *regularexpression = [[NSRegularExpression alloc]
                                              initWithPattern:patternStr
                                              options:NSRegularExpressionCaseInsensitive
                                              error:nil];
    
    NSArray<NSTextCheckingResult *> *matches = [regularexpression matchesInString:content options:NSMatchingReportProgress range:NSMakeRange(0, content.length)];
    
    NSLog(@"真正使用的方法:before - count:%ld", matches.count);
    NSMutableSet *set = [NSMutableSet set];
    for (NSTextCheckingResult *result in matches) {
        NSRange range2 = [result rangeAtIndex:1];
        NSString *method = [content substringWithRange:range2];
        [set addObject:method];
    }
    NSLog(@"真正使用的方法:after - count:%ld", set.count);
    return set;
}

/*
 * 所有的方法。
 * 通过buildSetting->LinkMap设为yes且设map路径生成文件
 */
- (NSMutableSet *)testFile {
    NSError *error;
    NSString *content = [NSString stringWithContentsOfFile:@"/Users/a58/linkMap.txt" encoding:NSASCIIStringEncoding error:&error];
//    NSString *patternStr = [NSString stringWithFormat:@"([+-]\\[.+\\s(.+)\\])"];
    NSString *patternStr = [NSString stringWithFormat:@"[+-]\\[[0-9a-zA-Z_]+\\s([0-9a-zA-Z_:]+)\\]\\n"];
    NSRegularExpression *regularexpression = [[NSRegularExpression alloc]
                                              initWithPattern:patternStr
                                              options:NSRegularExpressionCaseInsensitive
                                              error:nil];
    
    NSArray<NSTextCheckingResult *> *matches = [regularexpression matchesInString:content options:NSMatchingReportProgress range:NSMakeRange(0, content.length)];
    
    NSLog(@"所有方法:before - count:%ld", matches.count);
    NSLog(@"正在去重...");
    NSMutableSet *set = [NSMutableSet set];
    for (NSTextCheckingResult *result in matches) {
        NSRange range2 = [result rangeAtIndex:1];
        NSString *method = [content substringWithRange:range2];
        [set addObject:method];
    }
    NSLog(@"所有方法 after - count:%ld", set.count);
    [[set allObjects] writeToFile:@"/Users/a58/link-sel" atomically:YES];
    return set;
}

打印的日志如下:

2018-12-07 19:28:41.909175+0800 TestMachO2[80125:1791939] 所有方法:before - count:53987
2018-12-07 19:28:41.909410+0800 TestMachO2[80125:1791939] 正在去重...
2018-12-07 19:28:41.971372+0800 TestMachO2[80125:1791939] 所有方法 after - count:27194
2018-12-07 19:28:42.014835+0800 TestMachO2[80125:1791939] 真正使用的方法:before - count:23796
2018-12-07 19:28:42.042791+0800 TestMachO2[80125:1791939] 真正使用的方法:after - count:23796
2018-12-07 19:28:42.042883+0800 TestMachO2[80125:1791939] 所有方法count:27194, 真正使用的方法count:23796
2018-12-07 19:28:42.042911+0800 TestMachO2[80125:1791939] 正在相减...
2018-12-07 19:28:42.053201+0800 TestMachO2[80125:1791939] 无用方法的count:6709, 包含set方法
2018-12-07 19:28:42.055813+0800 TestMachO2[80125:1791939] 去除set方法 2633个
2018-12-07 19:28:42.057631+0800 TestMachO2[80125:1791939] 最终无用方法的count:4076个
2018-12-07 19:28:42.062334+0800 TestMachO2[80125:1791939] 还是不行,包含getter方法!平时直接用_变量并不调getter方法;并且包含第三方的无用方法

结论

最终找出无用的方法4076个。
但是getter方法和第三方的库的方法混在其中,无法剔除,只能通过人工一个一个查看来进行筛选。所以还需要尝试其它更好的方式!!!

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Mach-O 概述 和 部分命令介绍 我们知道Windows下的文件都是PE文件,同样在OS X和iOS中可执行文...
    青花瓷的平方阅读 15,044评论 2 52
  • 命令汇总 file XXX查看macho文件架构信息和是否是动态库 从上面信息可以看出来,dyld是一个dynam...
    繁星mind阅读 2,940评论 5 3
  • 资源优化 1. 去除无用资源 一般都是版本迭代过程中存在的图片资源。可以借助三方工具来解决: Unused-mas...
    RobinZhao阅读 2,281评论 2 24
  • LinkMap诡探 Xcode中配置LinkMap LinkMap文件是Xcode产生可执行文件(Mach-O)的...
    coder_feng阅读 594评论 0 0
  • 熟悉Linux和windows开发的同学都知道,ELF是Linux下可执行文件的格式,PE32/PE32+是win...
    Klaus_J阅读 4,022评论 1 10