iOS开发针对对Masonry下的FPS优化讨论
今天博客的內(nèi)容就系統(tǒng)的討論一下Masonry對FSP的影響,以及如何更好的使用Masonry。如果你對iOS開發(fā)足夠熟悉的話,那么對Masonry框架應(yīng)該不陌生。簡單的說,Masonry的誕生讓AutoLayout的使用更為優(yōu)雅,讓控件的布局更為方便。使用辯證的觀點來看一個事物的話,凡事都有兩面性,Masonry的使用也不例外。Masonry框架的使用不當(dāng)會直接影響當(dāng)UI的FPS。今天我們就來討論一下在使用Masonry時的一些誤區(qū),看一下那些影響性能的使用方式。本篇博客我們依然會依托于Demo來敘述的一些東西。
之前寫過一篇文章是專門來介紹Masonry框架的,并且對該框架的源碼進(jìn)行了相關(guān)解析,詳細(xì)內(nèi)容請移步于《iOS開發(fā)之Masonry框架源碼解析》。
一、Demo綜述
1.運行效果
先入為主,本篇博客的內(nèi)容依然是依托于我們特意為本篇博客所打造的Demo的,首先我們先來看一下Demo運行起來是怎樣的效果,通過Demo我們可以看到那些問題,以及這些問題是如何被解決的。下方就是我們本篇博客所涉及Demo的運行效果。?
從下方的運行效果不難看出,我們是分了6種情況來觀察和判斷Masonry的各種使用方式對FPS的影響如何。上方通過六個SegmentControl可以去切換Cell的布局方式。當(dāng)然每種布局方式所呈現(xiàn)出來的Cell是相同的。這樣也是做實驗時保持實驗項改變其他項保持一致的原則。我們可以通過右下方FPS指示器來直觀的感受一下FPS的變化趨勢。下方這個FPS顯示控件是從我們之前的Demo中拿過來的。之前的Demo也是關(guān)于FPS優(yōu)化的,只不過是關(guān)于Cell高度動態(tài)計算的FPS優(yōu)化,詳情請移步于《iOS開發(fā)之多種Cell高度自適應(yīng)實現(xiàn)方案的UI流暢度分析》。
下方Cell中所顯示的數(shù)據(jù)時隨機生成的,左邊的Image也是隨機取的。右邊的Title和Detail都是NSAttributedString并且下方的有些Detail有可能為空。如果某一條的Detail為空,那么該條Detail下方的所有內(nèi)容的布局上移。稍后會詳細(xì)的介紹該Demo以及其中的技術(shù)點。
2、模擬網(wǎng)絡(luò)請求
上面Cell中顯示的數(shù)據(jù)是通過模擬網(wǎng)絡(luò)數(shù)據(jù)來獲取的,下方就是我們的模擬網(wǎng)絡(luò)層的相關(guān)代碼。畢竟是Demo,并且Demo的重點不在網(wǎng)絡(luò)層上,下方就簡單的寫了一下,代碼比較簡單。就是一個單例+一個模擬數(shù)據(jù)隨機生成的方法,然后把這個隨機生成的數(shù)據(jù)通過Block回調(diào)到網(wǎng)絡(luò)層的使用者上。具體代碼如下所示:
3、上述Cell的基類XBaseTableViewCell
上面每種Segment中的Cell都是一種獨立的Cell類型,不過這些Cell有一個共同的父類。而這個父類就負(fù)責(zé)來處理這些Cell所共用的邏輯。下方的這個XBaseTableViewCell就是上述顯示的所有Cell的基類。其中聲明并初始化了Cell上的所有控件。并且提供了相關(guān)的設(shè)置值的方法。
從下方的代碼中不難看出,有兩個方法是需要子類進(jìn)行重寫的,一個是給控件添加布局的方法addLayoutSubviews, 另一個就是更新布局的方法updateLayoutSubviews方法。每個子類中都會對這兩個方法進(jìn)行重寫并給出不同的布局方式。
4、Segment中切換Cell的代碼????
下方是在相應(yīng)的VC中的點擊SegmentControl的邏輯代碼, 點擊不同的Segment會選擇不同的Cell然后刷新TableView,代碼比較簡單就不做過多的贅述了。
二、對上述各種的布局方式進(jìn)行分析
接下來要做的事情就是分析一下每種布局方式對FSP的影響,下方會對不同的布局情況使用Instrument進(jìn)行分析并看一下具體的數(shù)據(jù)。下方分別討論了只使用Masonry的Update操作、Remake操作、先Make后Update、Frame操作以及先Make后Frame操作。
1、update
首先我們來看一下update操作。也就是使用update直接給控件賦值,這是比較偷懶的一種操作。因為在我們的Demo中在設(shè)置cell的值時會更新一些控件的UI布局,所有我們索性就直接使用Masonry的update,直接給控件添加約束。在Masonry中的update操作有個特點,就是update一個約束會先在已添加的約束數(shù)組中找到該約束,然后更新該約束,如果找不到就install添加相應(yīng)的約束。從這個update的功能來看其效率是比較低的。
我可以先看一下代碼實現(xiàn),在子類XUpdateLayoutTableViewCell中,重寫了addLayoutSubviews和updateLayoutSubviews兩個方法。在updateLayoutSubviews方法中,為所有的控件使用update的方式添加約束。下方這樣寫會在每次設(shè)置值的時候都會調(diào)用下方的updateLayoutSubviews方法,這樣就會更新cell上的控件的所有布局,當(dāng)然,不建議這樣去做,因為這樣會更新那些不需要更新的約束。之所以今天羅列出來,是因為在開發(fā)中下方的問題確實存在,也許是因為時間緊張,也許是因為其他原因?qū)е碌南路竭@種代碼實現(xiàn)。
我們先來使用Instruments跑一下上述的Demo,然后直觀的感受一下該Demo的Core Animation的直觀表現(xiàn)。下方就是我們將SegmentControl切換到Update時所對應(yīng)的FPS數(shù)據(jù)。從下方的數(shù)據(jù)我們不難看出,直接用Update添加更新約束這種做法是比較影響FPS的。當(dāng)然,Cell中還會使用到屬性字符串,這個我們稍后會討論一下的。
我們可以來跑一下Update狀態(tài)下的Time Profile。如下所示,從下方的結(jié)果中不難看出,在Cell更新數(shù)據(jù)時,有兩塊的操作比較耗時。一個是Masonry的update操作,另一個則是Label設(shè)置NSAttributedString的操作。因為我們使用的每個Label都會賦值一個屬性字符串,這個是比較耗時的操作。還有一個要明確一點的是,屬性字符串的創(chuàng)建和生成并不會占用多少時間,而屬性字符串的賦值和渲染所占用的時間是比較多的,這一點從下方的Time Profile中也是不難看出的。
2、remake
接下來我們在來看一下Remake操作,從下方的Core Animation的結(jié)果中不難看出,其所表現(xiàn)出來的效果還不如使用Update操作呢。下方的FPS比Update要低一些,這也與remake自身的操作有關(guān)系,remake從字面意思來看就是重新制作,如果之前已經(jīng)添加過約束的話就先移除掉,然后再添加新的約束。
下方是Remake所對應(yīng)的Time Profile,從結(jié)果中我們可以看出布局更新占用了66.6%的耗時,而且33%的install耗時中uninstall占用了10%左右的開銷。在Masonry中remake效率是最低的。稍后我們會繼續(xù)進(jìn)行討論。
3、make + update
討論完update和remake, 我們來討論一下使用Masonry的常規(guī)做法。就是使用make來初始化控件的布局,使用update來更新所需要更新的約束。因為代碼比較簡單,就不一一往上貼了,但是跑一下使用Instrument跑一下還是很有必要的。下方是make + update 的方式的Core Animation所跑出來的結(jié)果。但從下方的FSP結(jié)果來看,還是要比之前只使用update或者remake的效果要好一些的,不過下方的FPS還是不高,稍后我們會將下方的數(shù)據(jù)進(jìn)行細(xì)化。
該部分的Time Profile就不跑了,因為設(shè)置值的時候我們依然采用的Update來更新的約束,只不過不是更新所有的約束,而是更新那些只需要更新的約束。因為更新的約束的量會少一些,所有FPS的表現(xiàn)效果會比之前更新所有的約束會更好一些。make + update的方式會是FPS稍微改善一些,但是從下方的圖中我們可以看出,改善的并不是特別好。
4、frame + frame
接下來,我們就不用Masonry來布局了,我們直接使用Frame布局。因為Autolayout最終仍然會轉(zhuǎn)換為Frame布局的,很顯然Frame布局在性能方面是優(yōu)于Autolayout布局的。接下來我們就來使用Frame布局然后使用Frame更新。下方的FPS還算說得過去,不過還不是滿格,其大部分原因就是因為NSAttrubitedString的原因了。
我們可以看一下更新Frame的Time Profile,如下所示。從下方的截圖中,我們不難看出update frame的時間占比只占到了2.5%,之前更新約束能占到60%左右,可以看到使用Frame布局的好處。從下方的分析結(jié)果中不難看出,現(xiàn)在影響FPS主要因素已經(jīng)從更新布局轉(zhuǎn)化到了AttributeString的設(shè)置。這也是上述FPS沒有滿格的原因。
6、make + frame
Masonry的誕生就是為了方便控件布局的,Frame布局不夠靈活,適配起來比較繁瑣,所以才有了AutoLayout。不過雖然AutoLayout可以很方便的適配屏幕,可是其性能方面表現(xiàn)的不是特別好。那么我們可不可以將兩者進(jìn)行結(jié)合呢。也就是說使用make來初始化控件的布局,使用Frame來更新布局。當(dāng)然這一過程不是簡單的在設(shè)置值的時候更新一下Frame就可以的,因為在Cell設(shè)置值的時候去更新Frame是沒用的,因為更新完Frame后,在渲染顯示的時候,還是會按照AutoLayout的布局來顯示的。我們需要做的是將Frame布局放到Autolayout布局之后,此處我們要做的就是將更新Frame的相關(guān)代碼放到下一個Runloop中來執(zhí)行。更新Frame代碼如下:
在cell中是make初始化控件布局,使用Frame更新布局,和Frame+Frame的方式差不多,只不過是使用Masonry布局時,在首屏加載的時候不如Frame布局,以后更新是一樣的。下方是使用Masonry+Frame的形式的Core Animation的結(jié)果。效果雖然比上一部分會稍微差一些,但是最終的效果還是滿Ok的。
?三、總結(jié)
本篇博客只討論Masonry的布局方式對FPS的影響,至于上述的NSAttributeString的問題不做過多贅述了。如果根據(jù)業(yè)務(wù)需要,有許多富文本的展示影響了FPS的話,那么可以采用其他的方式來進(jìn)行優(yōu)化,比如使用AsynDisplayKit所提供的相關(guān)Node進(jìn)行顯示等等。在博客的結(jié)尾,還是有必要做一個總結(jié)的。
下方是我們在代碼中更為細(xì)化的數(shù)據(jù),從數(shù)據(jù)中不難看出Remake的性能是最差的,所以我們在使用Masonry時盡量要少使用Remake。對控件的更新只一味的選擇使用Update也不是一個好的選擇,如果要使用Masonry框架還要對控件進(jìn)行布局更新的話,最好是把那些不變的約束和需要更新的約束分開。使用make來添加相關(guān)約束,使用update來修改需要更新的約束。當(dāng)然使用Frame布局的性能會好一些,不過布局過程過于繁瑣不便于進(jìn)行屏幕的適配。當(dāng)然也可以使用Masonry進(jìn)行布局使用Frame進(jìn)行布局的更新,當(dāng)然需要注意的是Frame布局更新的時機,需在Autolayout加載的時機后進(jìn)行。
下方是進(jìn)行了統(tǒng)一的數(shù)據(jù)統(tǒng)計,當(dāng)然是針對本篇博客所對應(yīng)的Demo的。下方表格中統(tǒng)計了一次更新cell布局所采用的不同方式的平均時間,從下方的數(shù)據(jù)中我們不難看粗Remake的更新布局用時最多,消耗了12+ms, 而Update所有的約束用時也是不少,一次更新布局使用了9+ms。而只更新需要更新的布局用時7+ms, 稍微要比更新所有的布局要好一些。當(dāng)然直接修改Frame的用時最少,只用了0.06+ms的時間,從該數(shù)據(jù)可以直觀的感受到Frame布局的效率性。
而右邊還給出了一個屬性字符串的創(chuàng)建和賦值的用時,其中我們可以看到,屬性字符串的創(chuàng)建耗時并不是太多,而比較耗時的是屬性字符串的賦值,每次賦值占用了0.7ms, 如果是10個的話,那么賦值時間就是7ms, 如果屬性字符串的內(nèi)容再復(fù)雜一些,那么用時肯定會比這個高。當(dāng)然我們可以使用第三方提供的一些控件和方法將這部分時間給優(yōu)化掉,這個可以放到以后再討論。
今天的博客就到這兒吧,目的是在使用Masonry時要合理的進(jìn)行使用,有必要時,可以使用Frame進(jìn)行布局。
上述demo -github分享鏈接:https://github.com/lizelu/FPSProfileDemo
?
?
原文地址:http://www.cocoachina.com/ios/20171116/21197.html
?
轉(zhuǎn)載于:https://www.cnblogs.com/SUPER-F/p/8963850.html
總結(jié)
以上是生活随笔為你收集整理的iOS开发针对对Masonry下的FPS优化讨论的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JavaScript表单验证年龄
- 下一篇: rp文件转换成html,Axure产品原