前言
我还在上一个东家的时候,我现在东家的项目写了几个功能作为外包给我做了,所以没来这家公司的时候我对这个项目就比较熟悉了;前年从上家公司离职后受邀来到现在这家公司了。接手这个APP因为急着上线功能,所以我也没有对APP进行优化,先前是三个程序员开发的,上线以后APP包达到116M,每次运营出去推广下载是个痛苦的事,非常的慢,所以每次运营的小伙伴出去推广,都会带上地推盒子,我每次都会把最新的ipa放到地推盒子里,给运营小伙伴用......说多了都是泪。所以下决心挤时间来优化安装包。
安装包的优化是个细致漫长的过程,我这里会把我做的事一一描述出来,以供大家参考。
1.大文件移除
我们APP开发设计的时候,老总选择的是PingFangSC字体,但是有一个问题就是在iOS9.0以前手机字体库是没有PingFangSC字体库的,这就需要我们手动导入PingFangSC字体库,但是涵盖几个常用的PingFangSC字体库大概有三四十兆,所以这也找出APP包比较大的一个重要原因,但是iOS9.0以后根本又不需要了,所以PingFangSC字体又不是每个包必须的。因此我把PingFangSC字体库拿出来放在公司服务器上,拿到下载链接,让用户下载完成APP以后再在手机里面下载字体库。平方字体参考:《 iOS-PingFangSC字体》
具体处理思路是:我通过runtime写了一个替换fontWithName的方法,里面进行判断如果用户第一次打开APP还是加载系统自带的字体库,然后在APP内下载字体库,下载完成以后解压加载,再打开新的页面就替换上去了。
总结:我们可以把项目中大的资源文件或者包放在服务器上,等APP下载以后在下载下来,这个思路也可以用在更新framework上,参考本人的另一篇文章:《 [置顶] iOS-OC-APP热更新,动态更新(仿QQ打开或关闭某个功能)》。
2.图标管理优化
开始项目中的图标文件是被小伙伴们直接放在工程目录下面的,里面有1x、2x和3x的图片,当然打包的时候这些文件也都被打包进去了。我这里做的就比较简单了我把图片放在Xcode自带的图片管理工具里面Images.scasssets,这样的好处就是打包的资源包中的图片会被放到Assets.car.图片有被压缩;此时若用[[NSBundle MainBundle] pathForResource: ofType: ]来访问时访问不到的。同时你也无法像平常一样轻易的拿到被人的图片资源了,不用再为多像素的图片命名。mages.xcassets会自动的排列不同像素的图片。
还有就是一些常用的小图标,可能样式是一样的,但是就是颜色不一样,这样在工程中也很多;我这里用到iconfont来替换png图标,用起来还简单,不但减小了资源文件的占用空间还方便使用。
最后就是删除工程中不用的icon图标了。
3.相同功能控件的封装
我们在开发中肯定会遇到相同控件或者功能,也有可能就是不同的UI但是功能差不多。这里面我将距离相同功能相同UI的和相同功能不同UI的两个示例。
a.相同功能和UI
我们把项目中常用的相同功能和UI的部门拿出来封装成一个单独的功能,开发使用直接调用就行了。比如我项目中的点赞和打分控件,点赞是我自定义的一个ZFJPraiseBtn,打分是我自定义的一个ZFJScoreView,封装以后开发者需要使用的时候直接给一个点赞数或者分数的回调就行了,一句代码就搞定。示例图如下:
b.功能相同UI不同
有些东西功能相同的,但是UI不同,比如我的界面有滚动和轮播功能,只需要传入不同的view就行,如下图的头部广告轮播滚动、推荐比赛左右滑动、推荐文章左右滑动:
还有我们的APP类似于微信的朋友圈,可以发图片文字或者视频,对应的列表有全文本、图片0~9张,我只需要写一个统用的cell管理类,传入数据模型model返回cell就行,如下面的方法:
/** Blog列表Cell @param cell HomePostCell @param indexPath indexPath @param model 数据模型 */ - (void)setNewHomePostCell:(HomePostCell *)cell cellForRowAtIndexPath:(NSIndexPath *)indexPath model:(ZFJBlogsModel *)model;
引用如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{ static NSString *identifier = @"HomePostCell"; HomePostCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier]; if(cell == nil){ cell = [[HomePostCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier isShowSpace:YES]; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.delegate = self; cell.authorVoiceBubble.delegate = self; cell.replyVoiceBubble.delegate = self; } if(self.dataArray.count>0){ [[ZFJViewManager manager] setNewHomePostCell:cell cellForRowAtIndexPath:indexPath model:self.dataArray[indexPath.row]]; } return cell; }
试用APP中所以的帖子类型的列表。
4.第三方库的精简
第三方库的使用是项目中不可避免的,我们在开发过程中为了节约开发的时间成本和财力成本,我们经常会使用一些第三方库。我们APP在项目中用到IM即时聊天,我们选用的是融云的IM聊天库,融云IM注释详细接入方便,融云IM有IMKit和IMLib两种库,如果你使用融云IM的UI那你就要把这两张库都导入,但是这两种库都导入的话占用不少容量,光磁盘大小就有44M了,但是我们APP的聊天场景比较简单,就是单聊和群聊,所以这里面我删除了IMKit库,在IMLib的基础上自己写聊天UI,这样又精简了不少内存。如下图:
总结:我们在使用第三方库的时候可以根据自己的需求选择性的使用。
5.基类的使用
基类是每个初学者都应该知道的,当然在开发过程中也是非常实用的,我们把一些常用的或者同样的方法放在基类里面,这样继承基类的类也都能使用。举例:友盟统计方法我写在BaseViewController里面,代码如下:
- (void)viewWillAppear:(BOOL)animated{ [super viewWillAppear:animated]; [MobClick beginLogPageView:self.title]; } - (void)viewWillDisappear:(BOOL)animated{ [super viewWillDisappear:animated]; [MobClick endLogPageView:self.title]; }
6.代码精简
代码精简是开发者的思维习惯和开发习惯所决定的,还有就是你的开发年限。比如我现在有一个数组让你来去重,这就要很多种方法了,但是不同的方法所产生的代码就不一样了,但是结果是一样的,比如:
方法一:
NSMutableArray *categoryArray = [[NSMutableArray alloc] init]; for (unsigned i = 0; i < [nameArray count]; i++){ if ([categoryArray containsObject:[nameArray objectAtIndex:i]] == NO){ [categoryArray addObject:[nameArray objectAtIndex:i]]; } }
方法二:
NSSet *set = [NSSet setWithArray:arr]; NSLog(@"%@",[set allObjects]);
很明显方法二的代码少于方法一,但是达到的效果也是一样的。
还有就是删除无用的代码,APP在开发过程中,因为版本的迭代,时间久了会产生很多无用的类或者代码,这样我会选择删除,如果害怕以后会用得到,你可以选择先备份一份,当然在备份的时候要弄一份备份文档是最好不过的了。
结束语
欢迎各位大神补充!
欢迎大家加移动开发技术交流群,在这里大家可以一起讨论学习,这里有大佬,也有小菜鸟,没事还能斗斗图装装逼,如果需要换工作的还能相互推荐,期待大家的加入!