ios 經(jīng)典面試案例 (五)

1.OS app啟動如何優(yōu)化望伦?

1. 我們可以通過在 Xcode 中 Edit scheme -> Run -> Auguments 將環(huán)境變量 DYLD_PRINT_STATISTICS 設(shè)為 1,在控制臺看到main()函數(shù)之前的啟動時(shí)間。

2. 分解優(yōu)化目標(biāo) 分步達(dá)到優(yōu)化目的

   1). 耗時(shí)操作異步處理

   2). 如果啟動流程依賴網(wǎng)絡(luò)請求回來才能繼續(xù),那么需要考慮網(wǎng)絡(luò)極差情況下的啟動速度

   3). 如果APP有l(wèi)oading廣告頁并且對分辨率的要求較高,請嘗試做緩存吧

   4). 主頁面Controller中的viewDidLoad和viewWillAppear方法中盡量少做事情

   5). 排查清理項(xiàng)目中未使用到的類庫以及Framework

   6). 刪減合并一些OC類,刪減沒有用到或者可以不用的靜態(tài)變量肪笋、方法等

   7). 輕量化+load方法中的內(nèi)容,可延遲到+initialize中

2.copy與mutableCopy的理解?

使用copy或mutableCopy方法可以創(chuàng)建一個對象的副本

copy

需要實(shí)現(xiàn)NSCoppying協(xié)議

這些創(chuàng)建的是不可變副本(如NSString潮罪、NSArray兼犯、NSDictionary)

Copy的目的是建立副本,同時(shí)修改原始對象和復(fù)本不會互相干擾

mutableCopy

需要先實(shí)現(xiàn)NSMutableCopying協(xié)議

創(chuàng)建的是可變副本(如NSMutableString、NSMutableArray合蔽、NSMutableDictionary)

3.UITableView性能優(yōu)化

1)Cell重用

  • 1.1>數(shù)據(jù)源方法優(yōu)化
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

在可見的頁面會重復(fù)繪制頁面,每次刷新顯示都會去創(chuàng)建新的Cell满粗,非常耗費(fèi)性能辈末。
** 解決方案:**首先創(chuàng)建一個靜態(tài)變量reuseID(代理方法返回Cell會調(diào)用很多次,防止重復(fù)創(chuàng)建映皆,static保證只會被創(chuàng)建一次挤聘,提高性能),然后捅彻,從緩存池中取相應(yīng)identifier的Cell并更新數(shù)據(jù)组去,如果沒有,才開始alloc新的Cell步淹,并用identifier標(biāo)識Cell从隆。每個Cell都會注冊一個identifier(重用標(biāo)識符)放入緩存池,當(dāng)需要調(diào)用的時(shí)候就直接從緩存池里找對應(yīng)的id缭裆,當(dāng)不需要時(shí)就放入緩存池等待調(diào)用键闺。(移出屏幕的Cell才會放入緩存池中,并不會被release)所以在數(shù)據(jù)源方法中做出如下優(yōu)化:
// 調(diào)用次數(shù)太多澈驼,static 保證只創(chuàng)建一次reuseID辛燥,提高性能
static NSString *reuseID = “reuseCellID”;
// 緩存池中取已經(jīng)創(chuàng)建的cell

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseID];
  • 1.2>緩存池的實(shí)現(xiàn)
    當(dāng)Cell要alloc時(shí),UITableView會在堆中開辟一段內(nèi)存以供Cell緩存之用缝其。Cell的重用通過identifier標(biāo)識不同類型的Cell挎塌,由此可以推斷出,緩存池外層可能是一個可變字典内边,通過key來取出內(nèi)部的Cell榴都,而緩存池為存儲不同高度、不同類型(包含圖片漠其、Label等)的Cell嘴高,可以推斷出緩存池的字典內(nèi)部可能是一個可變數(shù)組,用來存放不同類型的Cell辉懒,緩存池中只會保存已經(jīng)被移出屏幕的不同類型的Cell阳惹。
  • 1.3>緩存池獲取可重用Cell兩個方法的區(qū)別
-(nullable __kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier; 
這個方法會查詢可重用Cell,如果注冊了原型Cell眶俩,能夠查詢到,否則快鱼,返回nil颠印;而且需要判斷if(cell == nil)纲岭,才會創(chuàng)建Cell,不推薦
-(__kindof UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(6_0);
 使用這個方法之前线罕,必須通過xib(storyboard)或是Class(純代碼)注冊可重用Cell止潮,而且這個方法一定會返回一個Cell

注冊Cell

- (void)registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(5_0);
- (void)registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier NS_AVAILABLE_IOS(6_0);

好處:如果緩沖區(qū) Cell 不存在,會使用原型 Cell 實(shí)例化一個新的 Cell钞楼,不需要再判斷喇闸,同時(shí)代碼結(jié)構(gòu)更清晰。

2)定義一種(盡量少)類型的Cell及善用hidden隱藏(顯示)subviews

  • 2.1>一種類型的Cell
    分析Cell結(jié)構(gòu)询件,盡可能的將 相同內(nèi)容的抽取到一種樣式Cell中燃乍,前面已經(jīng)提到了Cell的重用機(jī)制,這樣就能保證UITbaleView要顯示多少內(nèi)容宛琅,真正創(chuàng)建出的Cell可能只比屏幕顯示的Cell多一點(diǎn)刻蟹。雖然Cell的’體積’可能會大點(diǎn),但是因?yàn)镃ell的數(shù)量不會很多嘿辟,完全可以接受的舆瘪。好處:

    • 減少代碼量,減少Nib文件的數(shù)量红伦,統(tǒng)一一個Nib文件定義Cell英古,容易修改、維護(hù)
    • 基于Cell的重用昙读,真正運(yùn)行時(shí)鋪滿屏幕所需的Cell數(shù)量大致是固定的召调,設(shè)為N個。所以如果如果只有一種Cell箕戳,那就是只有N個Cell的實(shí)例某残;但是如果有M種Cell,那么運(yùn)行時(shí)最多可能會是“M x N = MN”個Cell的實(shí)例陵吸,雖然可能并不會占用太多內(nèi)存玻墅,但是能少點(diǎn)不是更好嗎。
  • 2.2>善用hidden隱藏(顯示)subviews
    只定義一種Cell壮虫,那該如何顯示不同類型的內(nèi)容呢澳厢?答案就是,把所有不同類型的view都定義好囚似,放在cell里面剩拢,通過hidden顯示、隱藏饶唤,來顯示不同類型的內(nèi)容徐伐。畢竟,在用戶快速滑動中募狂,只是單純的顯示办素、隱藏subview比實(shí)時(shí)創(chuàng)建要快得多角雷。

3)提前計(jì)算并緩存Cell的高度
在iOS中,不設(shè)UITableViewCell的預(yù)估行高的情況下性穿,會優(yōu)先調(diào)用”tableView:heightForRowAtIndexPath:”方法勺三,獲取每個Cell的即將顯示的高度,從而確定UITableView的布局需曾,實(shí)際就是要獲取contentSize(UITableView繼承自UIScrollView,只有獲取滾動區(qū)域吗坚,才能實(shí)現(xiàn)滾動),然后才調(diào)用”tableView:cellForRowAtIndexPath”,獲取每個Cell,進(jìn)行賦值呆万。如果項(xiàng)目中模塊有10000個Cell需要顯示商源,可想而知…

解決方案:我個人認(rèn)為,可以創(chuàng)建一個frame模型桑嘶,提前計(jì)算每個Cell的高度炊汹。參考其中一篇博客的時(shí)候,在解決這個問題的時(shí)候逃顶,可以將計(jì)算Cell的高度放入數(shù)據(jù)模型讨便,但這與MVC設(shè)計(jì)模式可能稍微有點(diǎn)沖突,這個時(shí)候我就想到MVVM這種設(shè)計(jì)模式以政,這個時(shí)候才能稍微有點(diǎn)MVVM這種設(shè)計(jì)模式的優(yōu)點(diǎn)(其實(shí)還是很不理解的)霸褒,可以講計(jì)算Cell高度放入ViewModel(視圖模型)中,讓Model(數(shù)據(jù)模型)只負(fù)責(zé)處理數(shù)據(jù)盈蛮。

4)異步繪制(自定義Cell繪制)
遇到比較復(fù)雜的界面的時(shí)候废菱,如復(fù)雜點(diǎn)的圖文混排,上面的那種優(yōu)化行高的方式可能就不能滿足要求了抖誉,當(dāng)然了殊轴,由于我的開發(fā)經(jīng)驗(yàn)尚短,說實(shí)話袒炉,還沒遇到要將自定義的Cell重新繪制

5)滑動時(shí)旁理,按需加載
開發(fā)的過程中,自定義Cell的種類千奇百怪我磁,但Cell本來就是用來顯示數(shù)據(jù)的孽文,不說100%帶有圖片,也差不多夺艰,這個時(shí)候就要考慮芋哭,下滑的過程中可能會有點(diǎn)卡頓,尤其網(wǎng)絡(luò)不好的時(shí)候郁副,異步加載圖片是個程序員都會想到减牺,但是如果給每個循環(huán)對象都加上異步加載,開啟的線程太多,一樣會卡頓烹植,我記得好像線程條數(shù)一般3-5條斑鸦,最多也就6條吧愕贡。這個時(shí)候利用UIScrollViewDelegate兩個代理方法就能很好地解決這個問題草雕。

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView

6)緩存View
當(dāng)Cell中的部分View是非常獨(dú)立的,并且不便于重用的固以,而且“體積”非常小墩虹,在內(nèi)存可控的前提下,我們完全可以將這些view緩存起來憨琳。當(dāng)然也是緩存在模型中诫钓。

7)避免大量的圖片縮放、顏色漸變等篙螟,盡量顯示“大小剛好合適的圖片資源”

8)避免同步的從網(wǎng)絡(luò)菌湃、文件獲取數(shù)據(jù),Cell內(nèi)實(shí)現(xiàn)的內(nèi)容來自web遍略,使用異步加載惧所,緩存請求結(jié)果

9)渲染

  • 9.1>減少subviews的個數(shù)和層級
    子控件的層級越深,渲染到屏幕上所需要的計(jì)算量就越大绪杏;如多用drawRect繪制元素下愈,替代用view顯示
  • 9.2>少用subviews的透明圖層
    對于不透明的View,設(shè)置opaque為YES蕾久,這樣在繪制該View時(shí)势似,就不需要考慮被View覆蓋的其他內(nèi)容(盡量設(shè)置Cell的view為opaque,避免GPU對Cell下面的內(nèi)容也進(jìn)行繪制)
  • 9.3>避免CALayer特效(shadowPath)
    給Cell中View加陰影會引起性能問題僧著,如下面代碼會導(dǎo)致滾動時(shí)有明顯的卡頓:
view.layer.shadowColor = color.CGColor;
view.layer.shadowOffset = offset;
view.layer.shadowOpacity = 1;
view.layer.shadowRadius = radius;

題的搬運(yùn)履因,不成敬意!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末盹愚,一起剝皮案震驚了整個濱河市栅迄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌杯拐,老刑警劉巖霞篡,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異端逼,居然都是意外死亡朗兵,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門顶滩,熙熙樓的掌柜王于貴愁眉苦臉地迎上來余掖,“玉大人,你說我怎么就攤上這事礁鲁⊙纹郏” “怎么了赁豆?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長冗美。 經(jīng)常有香客問我魔种,道長,這世上最難降的妖魔是什么粉洼? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任节预,我火速辦了婚禮,結(jié)果婚禮上属韧,老公的妹妹穿的比我還像新娘安拟。我一直安慰自己,他們只是感情好宵喂,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布糠赦。 她就那樣靜靜地躺著,像睡著了一般锅棕。 火紅的嫁衣襯著肌膚如雪拙泽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天哲戚,我揣著相機(jī)與錄音奔滑,去河邊找鬼。 笑死顺少,一個胖子當(dāng)著我的面吹牛朋其,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播脆炎,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼梅猿,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了秒裕?” 一聲冷哼從身側(cè)響起袱蚓,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎几蜻,沒想到半個月后喇潘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡梭稚,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年颖低,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捎琐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片挺物。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖壳坪,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情莺戒,我是刑警寧澤伴嗡,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站从铲,受9級特大地震影響瘪校,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜食店,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一渣淤、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧吉嫩,春花似錦、人聲如沸嗅定。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽渠退。三九已至忙迁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間碎乃,已是汗流浹背姊扔。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留梅誓,地道東北人恰梢。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓,卻偏偏與公主長得像梗掰,于是被迫代替她去往敵國和親嵌言。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容

  • 看到這幅畫的時(shí)候及穗,我就在想摧茴,是一個什么樣的女性畫出了這樣的一幅圖案,這個畫作給我的感覺是安靜埂陆,安靜中透出一些孤獨(dú)苛白。...
    周米啊閱讀 407評論 2 2
  • 爸爸看手機(jī)和抽煙和喝酒。在寫就寫媽媽的胺偈购裙?干活兒干活兒干活兒愛花那會兒這是媽媽讓除了干活就是干活,干活著摔。干活兒干活兒……
    大琪_b0d6閱讀 289評論 0 0
  • “太美了!”就在邁進(jìn)教室的瞬間缓窜,我的目光被孩子們制作的精美手抄報(bào)所吸引:有的色彩斑斕如夏日般絢爛、有的淡雅如...
    唯美兒閱讀 314評論 8 5
  • 計(jì)劃6件事,都一一完成了禾锤,或許還不夠完美私股。 白天工作總是很犯困,因?yàn)檎{(diào)了新位置恩掷,太陽直曬的關(guān)系嗎倡鲸?(午休不能少哪...
    Ada彩英閱讀 135評論 0 0