ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

         ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论
  今天博客的内容就系统的讨论一下Masonry对FSP的影响,以及如何更好的使用Masonry。如果你对iOS开发足够熟悉的话,那么对Masonry框架应该不陌生。简单的说,Masonry的诞生让AutoLayout的使用更为优雅,让控件的布局更为方便。使用辩证的观点来看一个事物的话,凡事都有两面性,Masonry的使用也不例外。Masonry框架的使用不当会直接影响当UI的FPS。今天我们就来讨论一下在使用Masonry时的一些误区,看一下那些影响性能的使用方式。本篇博客我们依然会依托于Demo来叙述的一些东西。

  之前写过一篇文章是专门来介绍Masonry框架的,并且对该框架的源码进行了相关解析,详细内容请移步于《iOS开发之Masonry框架源码解析》。

  一、Demo综述

  1.运行效果

  先入为主,本篇博客的内容依然是依托于我们特意为本篇博客所打造的Demo的,首先我们先来看一下Demo运行起来是怎样的效果,通过Demo我们可以看到那些问题,以及这些问题是如何被解决的。下方就是我们本篇博客所涉及Demo的运行效果。

  从下方的运行效果不难看出,我们是分了6种情况来观察和判断Masonry的各种使用方式对FPS的影响如何。上方通过六个SegmentControl可以去切换Cell的布局方式。当然每种布局方式所呈现出来的Cell是相同的。这样也是做实验时保持实验项改变其他项保持一致的原则。我们可以通过右下方FPS指示器来直观的感受一下FPS的变化趋势。下方这个FPS显示控件是从我们之前的Demo中拿过来的。之前的Demo也是关于FPS优化的,只不过是关于Cell高度动态计算的FPS优化,详情请移步于《iOS开发之多种Cell高度自适应实现方案的UI流畅度分析》。

  下方Cell中所显示的数据时随机生成的,左边的Image也是随机取的。右边的Title和Detail都是NSAttributedString并且下方的有些Detail有可能为空。如果某一条的Detail为空,那么该条Detail下方的所有内容的布局上移。稍后会详细的介绍该Demo以及其中的技术点。

  

ASO培训服务

 

  2、模拟网络请求

  上面Cell中显示的数据是通过模拟网络数据来获取的,下方就是我们的模拟网络层的相关代码。毕竟是Demo,并且Demo的重点不在网络层上,下方就简单的写了一下,代码比较简单。就是一个单例+一个模拟数据随机生成的方法,然后把这个随机生成的数据通过Block回调到网络层的使用者上。具体代码如下所示:

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  3、上述Cell的基类XBaseTableViewCell

  上面每种Segment中的Cell都是一种独立的Cell类型,不过这些Cell有一个共同的父类。而这个父类就负责来处理这些Cell所共用的逻辑。下方的这个XBaseTableViewCell就是上述显示的所有Cell的基类。其中声明并初始化了Cell上的所有控件。并且提供了相关的设置值的方法。

  从下方的代码中不难看出,有两个方法是需要子类进行重写的,一个是给控件添加布局的方法addLayoutSubviews, 另一个就是更新布局的方法updateLayoutSubviews方法。每个子类中都会对这两个方法进行重写并给出不同的布局方式。

  

ASO培训服务

 

  4、Segment中切换Cell的代码

  下方是在相应的VC中的点击SegmentControl的逻辑代码, 点击不同的Segment会选择不同的Cell然后刷新TableView,代码比较简单就不做过多的赘述了。

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  二、对上述各种的布局方式进行分析

  接下来要做的事情就是分析一下每种布局方式对FSP的影响,下方会对不同的布局情况使用Instrument进行分析并看一下具体的数据。下方分别讨论了只使用Masonry的Update操作、Remake操作、先Make后Update、Frame操作以及先Make后Frame操作。

  1、update

  首先我们来看一下update操作。也就是使用update直接给控件赋值,这是比较偷懒的一种操作。因为在我们的Demo中在设置cell的值时会更新一些控件的UI布局,所有我们索性就直接使用Masonry的update,直接给控件添加约束。在Masonry中的update操作有个特点,就是update一个约束会先在已添加的约束数组中找到该约束,然后更新该约束,如果找不到就install添加相应的约束。从这个update的功能来看其效率是比较低的。

  我可以先看一下代码实现,在子类XUpdateLayoutTableViewCell中,重写了addLayoutSubviews和updateLayoutSubviews两个方法。在updateLayoutSubviews方法中,为所有的控件使用update的方式添加约束。下方这样写会在每次设置值的时候都会调用下方的updateLayoutSubviews方法,这样就会更新cell上的控件的所有布局,当然,不建议这样去做,因为这样会更新那些不需要更新的约束。之所以今天罗列出来,是因为在开发中下方的问题确实存在,也许是因为时间紧张,也许是因为其他原因导致的下方这种代码实现。

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  我们先来使用Instruments跑一下上述的Demo,然后直观的感受一下该Demo的Core Animation的直观表现。下方就是我们将SegmentControl切换到Update时所对应的FPS数据。从下方的数据我们不难看出,直接用Update添加更新约束这种做法是比较影响FPS的。当然,Cell中还会使用到属性字符串,这个我们稍后会讨论一下的。

  

ASO培训服务

 

  我们可以来跑一下Update状态下的Time Profile。如下所示,从下方的结果中不难看出,在Cell更新数据时,有两块的操作比较耗时。一个是Masonry的update操作,另一个则是Label设置NSAttributedString的操作。因为我们使用的每个Label都会赋值一个属性字符串,这个是比较耗时的操作。还有一个要明确一点的是,属性字符串的创建和生成并不会占用多少时间,而属性字符串的赋值和渲染所占用的时间是比较多的,这一点从下方的Time Profile中也是不难看出的。

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  2、remake

  接下来我们在来看一下Remake操作,从下方的Core Animation的结果中不难看出,其所表现出来的效果还不如使用Update操作呢。下方的FPS比Update要低一些,这也与remake自身的操作有关系,remake从字面意思来看就是重新制作,如果之前已经添加过约束的话就先移除掉,然后再添加新的约束。

  

ASO培训服务

 

  下方是Remake所对应的Time Profile,从结果中我们可以看出布局更新占用了66.6%的耗时,而且33%的install耗时中uninstall占用了10%左右的开销。在Masonry中remake效率是最低的。稍后我们会继续进行讨论。

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  3、make + update

  讨论完update和remake, 我们来讨论一下使用Masonry的常规做法。就是使用make来初始化控件的布局,使用update来更新所需要更新的约束。因为代码比较简单,就不一一往上贴了,但是跑一下使用Instrument跑一下还是很有必要的。下方是make + update 的方式的Core Animation所跑出来的结果。但从下方的FSP结果来看,还是要比之前只使用update或者remake的效果要好一些的,不过下方的FPS还是不高,稍后我们会将下方的数据进行细化。

  该部分的Time Profile就不跑了,因为设置值的时候我们依然采用的Update来更新的约束,只不过不是更新所有的约束,而是更新那些只需要更新的约束。因为更新的约束的量会少一些,所有FPS的表现效果会比之前更新所有的约束会更好一些。make + update的方式会是FPS稍微改善一些,但是从下方的图中我们可以看出,改善的并不是特别好。

  

ASO培训服务

 

  4、frame + frame

  接下来,我们就不用Masonry来布局了,我们直接使用Frame布局。因为Autolayout最终仍然会转换为Frame布局的,很显然Frame布局在性能方面是优于Autolayout布局的。接下来我们就来使用Frame布局然后使用Frame更新。下方的FPS还算说得过去,不过还不是满格,其大部分原因就是因为NSAttrubitedString的原因了。

  

ASO培训服务

 

  我们可以看一下更新Frame的Time Profile,如下所示。从下方的截图中,我们不难看出update frame的时间占比只占到了2.5%,之前更新约束能占到60%左右,可以看到使用Frame布局的好处。从下方的分析结果中不难看出,现在影响FPS主要因素已经从更新布局转化到了AttributeString的设置。这也是上述FPS没有满格的原因。

  ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

ASO培训服务

 

  6、make + frame

  Masonry的诞生就是为了方便控件布局的,Frame布局不够灵活,适配起来比较繁琐,所以才有了AutoLayout。不过虽然AutoLayout可以很方便的适配屏幕,可是其性能方面表现的不是特别好。那么我们可不可以将两者进行结合呢。也就是说使用make来初始化控件的布局,使用Frame来更新布局。当然这一过程不是简单的在设置值的时候更新一下Frame就可以的,因为在Cell设置值的时候去更新Frame是没用的,因为更新完Frame后,在渲染显示的时候,还是会按照AutoLayout的布局来显示的。我们需要做的是将Frame布局放到Autolayout布局之后,此处我们要做的就是将更新Frame的相关代码放到下一个Runloop中来执行。更新Frame代码如下:

  

ASO培训服务

 

  在cell中是make初始化控件布局,使用Frame更新布局,和Frame+Frame的方式差不多,只不过是使用Masonry布局时,在首屏加载的时候不如Frame布局,以后更新是一样的。下方是使用Masonry+Frame的形式的Core Animation的结果。效果虽然比上一部分会稍微差一些,但是最终的效果还是满Ok的。

 ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论 

ASO培训服务
>ASO培训服务:iOS开发针对对Masonry下的FPS优化讨论

相关文章

添加微信,免费了解:

mmm

点击添加我为QQ好友:加好友