美文网首页Swift编程
iOS应用优化(持续更新)

iOS应用优化(持续更新)

作者: 贝尔特伦 | 来源:发表于2019-05-06 18:03 被阅读20次

    以下内容均来源于实际项目中总结和与朋友探究,以及网络资料。

    1,减少主线程执行内容(耗时)

    尽量的把数据和逻辑等放到异步里去,主线层只处理UI。这点大家应该都是潜移默化了。
    2,DB读取影响页面显示,及按钮响应(耗时)

    项目中不可或缺的会用到数据库,当然大部分只是用来做数据存储,但是也有很多是用来做功能的配置。大部分人在页面初始化时就去读取db,对于一些数据量少,业务少的项目来说,是无所谓的,但是不可忽略其在一定程度上影响了页面的加载,导致页面卡顿。每读一次db,耗时大概200ms以上,我遇到的也有3,4百毫秒,如果只有这一个耗时,那完全可以忽略,但是量变引起质变,因此我们不得不去解决它,解决方案是给它加一个缓冲,至于怎么加,诸位自己构思,每个开发者的做法不一样,不便多说。

    3,对本地图片加载, [UIImage imageNamed:@""]方法,提前加载(耗时)

    这个方法,咱们无时无刻都在用,但正因为无时无刻都在用,也忽略其一些问题,笔者再查项目中耗时的时候,发现init方法,竟然耗时两三百毫秒,进去具体一看,竟然是因为这个方法,用的太多,因图片大小不同,其耗时竟然一次20到50ms不等。因此如果这个方法在主线程中,要批量使用时,还是需要提前处理一下的,处理方式也很简单,提前在其它地方,使用这个方法,加载一下后面需要使用的图片就可以了。因为这个方法生成的UIImage对象,会在应用的bundle中寻找图片,如果找到则Cache到系统缓存中,后面再用那就快了。

    4,网络图片的异步加载(耗时)
    基本上大家都是使用SD来加载网络图片,这点没什么可说的,可能大家会遇到加载大图的问题,这点如果可以的话,就压缩下。步骤是图片加载完成后,拿到图片去压缩,然后清楚它原有的缓存,缓存你压缩后的图片。

    5,传值(图片和视频)(内存)

    量少可以忽略,虽然这些都是一瞬间的事,但有时候也挺头疼,如果咱们把图片,视频都转成对象或者data放到参数里,那么肯定会影响内存,因此能传名字,链接的尽量,不要直接传对象,这些之前都做了缓存,再读一遍不会有其它影响的。

    6,减少循环和递归的使用(耗时)

    循环是肯定耗时的,但是不可避免的会用到它,因此再开发时,我们就需要考虑如何去减少它的使用,来满足需求,这个需要大家自己去构思这个开发套路了,需要说的是,之前笔者看到的一篇文章,是比较 for循环,for in和数组的enum遍历,三个方法的耗时比较。
    for > enum 》 for in,最省时的是for in,但还是要根据自己实际情况去选择使用,不用刻意去关注这个。

    7,使用wkwebview替换uiwebview(内存)

    UIWebview的内存消耗是硬伤,但是它的坑确实也很多,对于老项目想要去一步到位的替换掉,是比较难得,但是在iOS12,我们已经看到,UIWebview已经退出了舞台,项目中,已经标出其只支持到12,建议使用WKWebview,因此开始逐步用wk替换webview把。

    8,地图使用的优化(内存)

    项目中如果频繁的加载地图,对内存的消耗是巨大的,因此要对其优化。根据项目中地图的作用,可以封装一个共用的地图,假如,你某一个页面上,有一个地图,在程序的整个生命周期都不会被销毁掉,而其它地方也需要用到地图,那么你可以考虑把这个地图做成一个共用的,单丝这样,你需要严谨的去处理其父视图,以及地图上的内容。还是需要根据需求,慎重决定。

    9,tabView高度缓存(耗时)

    这个适用于高度需要自适应时的使用,比如我在做IM的时候,图片,文本,视频,以及其它乱其它八遭的样式显示时,需要在复用的前提下,保证页面的流畅性,因此对cell的高度要做一次缓存,对于已经加载过的数据,在model中存下cell的高度,再次加载时,无需再去计算。

    10,减少formatter的使用(耗时)

    时间转换的方法formatter,也是比较耗时间的,因此不能滥用。

    11,善于运用系统的一些特性减少代码量(代码量)

    以我一个多态的使用,来感受一下,如何精简代码的。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //0:无封面;1:大图;2:三图;3:右图
    NSArray *cellIdArr = @[@"cell",@"bigCell",@"MoreCell",@"rightCell"];
    NSArray *cellClsArr = @[@"JRBaseTableViewCell",@"JRBigImgVTableViewCell",@"JRMoreImgVTableViewCell",@"JRRightImgVTableViewCell"];
    JRTTDataModel *model = _dataArray[indexPath.row];
    NSInteger celltype = model.coverMode.integerValue;
    
    JRBaseTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdArr[celltype]];
    if (cell == nil) {
        cell = [[NSClassFromString(cellClsArr[celltype]) alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdArr[celltype]];
    }
    [cell setDataModel:model];
    return cell;
    }
    

    实际上,多态对代码量的精简,更加恐怖,具体在于开发者如何的使用。
    12,善于使用封装,继承,多态(代码量)

    这三点是面向对象语言的三大特性,许多优秀高品质的代码,都是因对这三点的理解,而写出的,因此需要开发者不断的感悟,感悟,再感悟。当然实际项目中,我们可能没有太多时间去优化代码,因此,在我们开发的时候,可以多考虑一下,这三点能不能用到。
    重复的代码,是导致工作效率低下的主要原因。他不仅影响开发效率,更影响后期维护的难度。

    举个例子,笔者项目有个地方,逻辑经常改,UI也变动较少,因此,笔者将逻辑层,全部抽离,每次改动都是改逻辑层,是不是维护上省很多事,也不用考虑会影响到其它地方。

    13,不能滥用代理,block,通知。三者选其优(代码量)

    项目中代理的使用也是比较频繁的,但是并不能表示他能解决问题,从而就无节制的使用它,这样会一点点增加你的代码量,像有的,把子控件封装出去了,但是一个View无法处理页面跳转问题,因此写一个代理,来处理页面跳转,如果仅此而已也还能接受,但是因跳转而牵出的其它功能,比如数据的提取,点击量的处理等等,一步步的增加你主控制器的代码,像跳转这样的功能完全可以在view中处理掉。
    对于代理,block和通知的选择,这个需要开发者自己去考虑,那个在实际运用中,比较方便。如果你代码封装的比较深,那么代理肯定是跟不上节奏的。而使用block,要频繁的处理循环引用问题,使用通知,要处理通知的移除,不能导致内存泄漏等问题。

    14,优美的使用category(代码量)

    category对代码的精简,和逻辑剥离的作用也是比较明显的。
    比如:在项目架构时,需要使用推送,分享,支付等一堆功能,而这些功能都是需要在appdelegate里去注册使用,这个时候就可以使用category,将一个个功能模块剥离出去,当然还有更高级的方法,但这个是最简单,最容易维护的。

    15,多封装工具类(代码量)

    对于一些公用方法,使用比较频繁的,剥离出去,放到工具类中。比如正则,时间转换,坐标转换等等乱七八糟。

    前段时间很多的rac,mvvm什么的,打着代码精简,开发简单,易维护什么的旗号,其实也就是替你处理一些操作步骤什么的,如果你能把自己会的,运用的很好,那么你的代码也是很优美的。
    ps:好的代码,并不是用了什么高深的技术,更不是人人都难看懂的代码,而是大家都知道,只是你领悟的更深,运用的更灵巧而已。

    16,解决UITableView上拉加载抖动(交互)

    有时候在做自适应高度时,上拉加载数据,页面会上下抖动,这是系统预估高度在捣鬼,屏蔽掉就可以了。

    self.tableView.estimatedRowHeight = 0;
    self.tableView.estimatedSectionHeaderHeight = 0;
    self.tableView.estimatedSectionFooterHeight = 0;
    

    17,UITableView多次调用reloadData,导致页面短暂白屏(交互)

    在调用reloadData时,异步延迟一丢丢就可以了

    18,防止按钮频繁点击(交互)

    这个处理方式有很多了,我是自己写了个category,设置下时间。

    #import "UIButton+ZYOneTouch.h"
    @implementation UIButton (ZYOneTouch)
    - (void)setTimeDisWithTime:(NSTimeInterval)time{
    self.userInteractionEnabled = NO;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(time * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        self.userInteractionEnabled = YES;
    });
    }
    @end
    

    19,IM页面弹出键盘,输入框与键盘之间出现空白(UI)
    这种情况,大部分是项目中使用了第三方的键盘监听库,而第三方IM的UI是自己处理的这个功能的,这时候,把第三方的键盘功能屏蔽掉即可。

    - (void)viewWillAppear:(BOOL)animated{
          [super viewWillAppear:animated];
          [IQKeyboardManager sharedManager].enable = NO;
          [IQKeyboardManager sharedManager].enableAutoToolbar = NO;
    }
    
    
     - (void)viewDidDisappear:(BOOL)animated{
          [super viewDidDisappear:animated];
          [IQKeyboardManager sharedManager].enable = YES;
          [IQKeyboardManager sharedManager].enableAutoToolbar = YES;
    }
    

    笔者在努力回想曾经的优化经历,慢慢补充吧,也欢迎大家把自己的分享出来。

    转载请署名谢谢

    相关文章

      网友评论

        本文标题:iOS应用优化(持续更新)

        本文链接:https://www.haomeiwen.com/subject/gbyjnqtx.html