iOS ~ 项目瘦身
相关参考文章传送门 |
---|
iOS 可执行文件瘦身方法 -- bang |
iOS App可执行文件的组成 -- bang |
清理 iOS 项目不用的图片资源 -- 姜家志 |
使用 python 找出 iOS 项目中没有使用到的图片资源 -- hi_xgb |
主要方法
- 编译优化(这个部分本文未包涵,但是这是收效最快的方法,立竿见影!请读者自行查阅相关文章)
- 删代码
- 删压图片
具体实现
这里提供了几个python脚本,用于查找项目中没有被使用的图片资源和代码,下面会介绍使用方法、思路原理和需要注意的地方:
- find_all_func_list.py
- find_all_unuseful_swift_func.py
- find_all_unuseful_swift_file.py
- find_all_unuseful_imageset.py
- find_all_unuseful_png.py
- linkmap.js
执行脚本,主要删除如下
1、大段代码注释
2、没有被引用的类
3、没有被调用的方法
4、image.xcassets中没有被使用的图片资源
5、未被使用的png图片资源
6、压缩全部图片资源
7、第三方包的替换和删除
(一) 删除大段代码注释
删除大段代码注释,有些开发者不喜欢删代码,不用的代码会选择注释掉“// 。。。。”,笔者恰恰相反,喜欢代码整洁,逻辑清晰。
这个步骤很重要!!!
因为python脚本是通过纯文本匹配的方式操作的,如果后做这一步,或者不做这一步都对python的执行结果有很大影响。
(二) 删除没有被引用的类 (推荐)
# coding=utf-8
import glob
import os
import re
# 绝对路径,使用时改成自己项目的路径
rootDir = '/Users/Alice/Desktop/deja-ios/Deja'
path = '/Users/Alice/Desktop/deja-ios'
def scan_files(directory,prefix=None,postfix=None):
files_list=[]
for root, sub_dirs, files in os.walk(directory):
for special_file in files:
if postfix:
if special_file.endswith(postfix):
filename = os.path.join(root,special_file)
files_list.append(filename)
elif prefix:
if special_file.startswith(prefix):
filename = os.path.join(root,special_file)
files_list.append(filename)
else:
files_list.append(os.path.join(root,special_file))
return files_list
def find_un_used_swiftfile():
# swift_list = scan_files(rootDir, postfix=".swift")
# swift_filename = [os.path.basename(pic)[:-6] for pic in swift_list]
swift_list = scan_files(rootDir, postfix=".h")
swift_filename = [os.path.basename(pic)[:-2] for pic in swift_list]
unused_swift = []
for i in range(0, len(swift_list)):
pic_name = swift_filename[i]
command = 'ag --ignore-dir Pods -l "%s" %s' % (pic_name, path)
result = os.popen(command).read()
ary = result.split('\n')
if len(ary) == 3 :
unused_swift.append(swift_list[i])
print 'unUsedswift:"%s" \n%s' % (pic_name ,result)
swift_path = 'unUsedSwift.txt'
swifttex = '\n'.join(sorted(unused_swift))
os.system('echo "%s" > %s' % (swifttex, swift_path))
print 'unuse res:%d' % (len(unused_swift))
print 'Done!'
if __name__ == '__main__':
find_un_used_swiftfile()
$ python find_all_unuseful_swift_file.py
思路:
- 遍历拿到所有xxxx.swift 的文件名
- 'ag --ignore-dir Pods -l "%s" %s' % (pic_name, path) ,搜索文件夹下所有包含该文件名的所有文件
- 结果如果只包含该文件自身和project.pbxproj,则认为给xxx.swift 没有被调用
误差:
1.类名和文件名不同
2.作为基类,而子类也定义在该类当中
结论:
- 这是以swift为例,oc的原理一样。
- 遍历出来的结果并不完全正确,需要人工核查,再手工删除, 经过多次优化发现这是个有点丑但是蛮有用的脚本,贴别是在项目有巨大改动的版本后,效果明显。
(三) 删除没有被调用的方法
思路:
1.python find_all_func_list.py
:正则匹配出所有swift方法 存入allFunction.txt
2.python find_all_unuseful_swift_func.py
:allFunction.txt 中的每一个方法名,搜索.swift .h .m 文件 只能匹配一处的方法名 ,则认为没有被调用
误差:
1、 能匹配所有oc 和 swift方法名的正则表达式 NO
2、 匹配所有方法调用列表的正则表达式 NO
结论:
1、匹配到的只是一部分
2、还需人工审查和手工删除
3、下下策、不推荐、思路而已。 只是如果这样的方法很多的话,说明你的代码长期没有重构或者维护了。
(四)删除image.xcassets中没有被使用的图片资源 (推荐)
思路:
ios中使用Images Assets管理图片,图片资源都是放在这里面,项目中的图片资源会放到.imageset目录中,里面对应1x,2x和3x的图,还有一个Contents.json的描述文件。清除图片资源需要把这个目录清除。(UIImage imageNamed:”image”),所以需要搜索在项目中文件的文件,如果找到对于的"name",说明该图片是被使用的,不然的话该图片即可被清理掉。
python脚本:
# coding=utf-8
import glob
import os
import re
# 绝对路径,使用时改成自己项目的路径
path = '/Users/Alice/Desktop/deja-ios/Deja'
images = glob.glob('/Users/Alice/Desktop/deja-ios/Deja/Res/images.xcassets/*/*.imageset')
def find_un_used():
img_names = [os.path.basename(pic)[:-9] for pic in images]
unused_imgs = []
for i in range(0, len(images)):
pic_name = img_names[i]
command = 'ag "%s" %s' % (pic_name, path)
result = os.popen(command).read()
if result == '':
unused_imgs.append(images[i])
print 'unuseful_imageset: %s' % (images[i])
os.system('rm -rf %s' % (images[i]))
text_path = 'unusedImagesAssets.txt'
tex = '\n'.join(sorted(unused_imgs))
os.system('echo "%s" > %s' % (tex, text_path))
print 'unuse res:%d' % (len(unused_imgs))
print 'Done!'
if __name__ == '__main__':
find_un_used()
步骤:
1.$ python find_all_unuseful_imageset.py
2.# os.system('rm -rf %s' % (images[i])) 注释掉的这句是直接删除相应的imageset。(建议先检查,在使用这句直接删除)
误差:
1.基本没有误差,可以直接使用
2.特例:如“iamge_1”,可能在for循环中被使用,会被当成没被使用的imageset而删掉。这时需要一个ignoreList,当然需要具体问题具体分析。
结论:
1、有效的删除imageset,效果明显,强烈推荐!
(五) 删除未被使用的png图片资源
$ python find_all_unuseful_png.py
思路:
和删除无用ImageSet的思路一样
误差:
1、ImageSet的图片因为全部改名使用,全部被乱棍打死了。
2、Fitting Room中图片几乎都是for循环使用的,所以被当做未使用的。
结论:
1、完全不可靠,待改善
(六) 压缩全部图片资源
工具:ImageOptim:压缩一个文件夹下的所有图片,不建议一次性拖入整个项目,因为十分费时。
Tips:一般情况下美工给你的图片已经很小了,优化的空间不大,但是凡事有例外!
(七) 第三方包的替换和删除
node linkmap.js
输出为:可以通过linkmap统计每个.o目标文件占用的体积和每个.a静态库占用的体积
体积较大的酌情处理
开发中应该注意的地方
1、及时删除没用的注释、废弃的代码、图片等
2、变量名和文件名(等自定义的)尽量表意清晰和简短
3、冗余字符串:
代码上定义的所有静态字符串都会记录在在可执行文件的__cstring段,
如果项目里Log非常多,这个空间占用也是可观的,也有几百K的大小,
可以考虑清理所有冗余的字符串。另外如果有特别长的字符串,
建议抽离保存成静态文件,因为AppStore对可执行文件加密导致压缩率低,
特别长的字符串抽离成静态资源文件后压缩率会比在可执行文件里高很多。