技术干货:统计项目中图片使用情况

移动开发
随着项目开发推进和版本迭代,项目中总会存在一些无效的图片资源,这些无效图片往往会增加编译成本和包的大小。一个普通的iOS工程会有大约三分之一的图片是未使用的。

[[155011]]

随着项目开发推进和版本迭代,项目中总会存在一些无效的图片资源,这些无效图片往往会增加编译成本和包的大小。

一个普通的iOS工程会有大约三分之一的图片是未使用的。

常用的方法有:

1,利用工具;

2,利用脚本;

3,添加图片时候写图片名称的代码;

脚本&工具的原理大概是这样,在工程中搜图片名称,如果没有使用这个图片名称的话,则认为这张图片没有被使用并列举出来。这种做法不太精准:

1,遇到用imageview做动画(即imageView.animationImages)时候,一般开发人员都会喜欢用for循环加入所有图片,这样就会导致已使用图片被列举出来;

2,使用不同资源包时候,如果两个资源包有相同名称,但是有个资源包中的图片没被使用,这样就会导致未被使用的没列举出来;

诸如此类情况有很多。有人会说用第三种方法,但是手动添加这样比较费时,即下面这种场景:

例如,我们想跟踪在程序中每一个view controller展示给用户的次数:当然,我们可以在每个view controller的viewDidAppear中添加跟踪代码;但是这太过麻烦,需要在每个view controller中写重复的代码。创建一个子类可能是一种实现方式,但需要同时创建UIViewController, UITableViewController, UINavigationController及其它UIKit中view controller的子类,这同样会产生许多重复的代码。

上面一段是Method Swizzling中开篇的描述,确实人工手动添加难免会有漏掉,那么就要用苹果自带的方法集中处理。

我们可以通过Method Swizzling修改UIImage的调用方法,在UIImage中添加打印使用图片(或者路径)的方法,然后写到一个文件里,在项目结束时候将没有出现在文件中的图片删除即可(可以采用脚本删除,便捷准确)。

这种情况下,我们就可以写出如下Method Swizzling,如在代码所示:

  1. #import "ADeanImage+Hook.h" 
  2. #import  
  3. #import  
  4. @implementation UIImage (Hook) 
  5. + (void)initialize 
  6.     static dispatch_once_t onceToken; 
  7.     dispatch_once(&onceToken, ^{ 
  8.         [self adeanImageHook]; 
  9.     }); 
  10. + (void)adeanImageHook 
  11.     [self imageNameHook]; 
  12. + (void)imageNameHook  // 类方法调用方式 
  13.     Class class = object_getClass((id)self); 
  14.     SEL originalSelector = @selector(imageNamed:); 
  15.     SEL swizzledSelector = @selector(adean_imageNamed:); 
  16.     Method originalMethod = class_getClassMethod(class, originalSelector); 
  17.     Method swizzledMethod = class_getClassMethod(class, swizzledSelector); 
  18.       
  19.     BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod)); 
  20.     if (didAddMethod) 
  21.     { 
  22.         class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod)); 
  23.     } 
  24.     else 
  25.     { 
  26.         method_exchangeImplementations(originalMethod, swizzledMethod); 
  27.     } 
  28. + (UIImage *)adean_imageNamed:(NSString *)name 
  29.     UIImage *image = [self adean_imageNamed:name]; 
  30.     [self printImageNameToLocalWithImageName:name]; 
  31.     return image; 
  32. + (void)printImageNameToLocalWithImageName:(NSString *)name 
  33. #ifdef ADeanForTest 
  34.     { 
  35.         // 打印图片地址 
  36.         ADeanLog(@"adean_msg:  imagefile %@", IMAGEFILEFILE); 
  37.         FILE *fp; 
  38.         const char *imageFilePath =[IMAGEFILEFILE UTF8String]; 
  39.         const char *cImageName = [[NSString stringWithFormat:@"%@\n", name] UTF8String]; 
  40.         /*打开文件*/ 
  41.         if((fp = fopen(imageFilePath, "a")) == NULL) 
  42.         { 
  43.             ADeanLog("文件打开出错,请检查文件是否存在\n"); 
  44.         } 
  45.         else 
  46.         { 
  47.         } 
  48.         fputs(cImageName,fp); 
  49.         fclose(fp); 
  50.     } 
  51. #endif 
  52. @end 

这样只要在Appdelegate启动时候调用下[UIImage initialize]就可以将所有用到imageNamed:的图片都打印出来。 如果需要打印所有已使用图片,只需要将UIImage中所有的类方法和实例方法都Method Swizzling下。这样项目测试一遍就可以将所有已使用图片存到一张图片清单上,只要在用脚本语言删除项目中没在图片清单上的图片即可。 

注:

中文版的《Objective-C Runtime 运行时之四:Method Swizzling》《Method Swizzling》漏掉了原著中的一段代码注释:

  1. // When swizzling a class method, use the following:       
  2.  // Class class = object_getClass((id)self); 
  3.  // ... 
  4.  // Method originalMethod = class_getClassMethod(class, originalSelector); 
  5.  // Method swizzledMethod = class_getClassMethod(class, swizzledSelector); 

by Adorable Dean

at Nanjing, Jiangsu, China 

本文首发在Adorkable Dean‘s blog转载请注明原作者,如果你对这篇文章有更好的见解可以通过微信联系我。

利益相关:本篇文章所有涉及到的软件均为笔者日常所用工具,无任何广告费用。

责任编辑:倪明 来源: CocoaChina
相关推荐

2010-10-14 16:10:28

MySQL排序

2022-07-13 14:26:26

Linux

2018-07-06 14:52:49

Docker容器云服务

2017-01-18 21:57:14

2010-05-12 15:14:59

subversion管

2015-11-09 15:32:34

TorTor网络隐私网络

2010-06-02 11:06:15

Linux 内存监控

2017-11-30 18:42:22

PythonCPU脚本分析

2009-06-30 14:11:00

Hibernate缓存

2010-02-03 17:16:58

Linux内存使用

2009-02-03 09:49:00

FTP空间共享

2010-11-16 11:40:04

Oracle查询表空间

2009-12-14 17:25:20

Linux操作系统

2020-12-07 18:19:46

Common Lisp方言编程

2014-04-24 16:26:31

UbuntuUbuntu 磁盘Linux基础

2021-03-26 07:17:38

Linux命令磁盘

2010-04-16 10:00:06

Oracle查看表空间

2019-12-18 11:01:15

CIO年终系统

2009-06-16 09:18:26

Linux系统管理系统资源

2021-03-01 13:11:20

duf终端工具Linux
点赞
收藏

51CTO技术栈公众号