作為一名iOS開發(fā)程序員,你肯定能寫出TableView..但是這個(gè)TableView的性能到底怎么樣呢...那就那就仁者見仁智者見智了..
網(wǎng)上的文章一抄一大把.在這里作為一個(gè)彩筆的我...也給幾條建議吧...
1.cornerRadius
imageView.layer.cornerRadius = 10;
imageView.clipsToBounds = YES;
相信小伙伴們對(duì)cornerRaius并不陌生,如果在iOS8之前,在表格視圖中如果頻繁大量使用cornerRaius,就可能會(huì)對(duì)表格的性能產(chǎn)生影響...
你會(huì)發(fā)現(xiàn),視圖中用了cornerRaius的部分是紅色的...
可能單單這樣一個(gè)視圖沒什么問題,但是如果在tableView中會(huì)怎么樣...
在每個(gè)單元格中可能就會(huì)對(duì)性能產(chǎn)生一定的影響了...
為什么會(huì)影響呢?是因?yàn)樘O果對(duì)裁切做了透明效果的處理,混合模式變紅就是一個(gè)很好的說明,而這個(gè)alpha可能會(huì)對(duì)性能造成影響...
但是據(jù)說iOS8之后蘋果對(duì)cornerRaius做了優(yōu)化,理論上說對(duì)性能的影響降低了....
但是還是感覺很不爽啊....
所以咱們還是自己開啟圖形上下文自己畫把....
自己動(dòng)手豐衣足食....
// UIImage 分類方法
- (instancetype)jb_circleImage {
// 開啟圖形上下文 opaque 一定要寫YES 表示不透明
UIGraphicsBeginImageContextWithOptions(self.size, YES, 0);
// 范圍
CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);
// 填充顏色<這里的顏色就你來定拉~~>
[[UIColor whiteColor] setFill];
UIRectFill(rect);
// 裁剪
[[UIBezierPath bezierPathWithOvalInRect:rect] addClip];
// 繪制圖片到圓上面
[self drawInRect:rect];
// 獲得圖片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
// 結(jié)束圖形上下文
UIGraphicsEndImageContext();
return image;
}
親愛的小伙伴,是不是看到綠色就舒服多了....
如果你說反正也這個(gè)顏色也不在頭上我也沒辦法...
誰讓它不是王寶綠呢...
上面那個(gè)分類方法我是用貝塞爾路徑切的,如果用上下文切也是可以的,調(diào)用CGContextClip(context)這個(gè)小函數(shù),不過要多獲取一下上下文~
2.緩存Cell的行高
各位小伙伴,如果你遇到Cell高度不同的時(shí)候是怎么處理的呢,相信老程序員們都還記得木有自動(dòng)布局的那一段用frame計(jì)算行高的輕松的時(shí)刻....
而后來,我們有了AutoLayout,僅僅是因?yàn)樘O果的機(jī)型變多了,從iPhone4,5,6,6+,iPadAir,Pro....
各種各樣的機(jī)型層出不窮,為了適配我們不得不選擇更為牛X的AutoLayout...
最開始我們用Autoresizing,然后蘋果讓我們用原生的那一長(zhǎng)串布局,然后蘋果發(fā)現(xiàn)那一串真的很長(zhǎng),于是出了VFL,然后發(fā)現(xiàn)VFL不太友好,又出了LayoutAnchors,但是最后我們選擇了Masonry/SnapKit.....
大部分小伙伴還是用Masonry的....吧.....
雖然不更新了.....
其實(shí)用Masonry真的是非常的簡(jiǎn)單加方便,相信用過的小伙伴們都會(huì)說好....
But用自動(dòng)布局來計(jì)算行高真的真的是非常消耗CPU,因?yàn)楸砀癜l(fā)生滾動(dòng)行高就要進(jìn)行計(jì)算,這是和之前用frame來計(jì)算行高是截然不同的,別看你只寫了兩句話(貌似第二句也不用寫了,那么就一句話)...
self.tableView.estimatedRowHeight = 100;
self.tableView.rowHeight = UITableViewAutomaticDimension;
系統(tǒng)在后臺(tái)要一直幫你拼命的計(jì)算行高啊啊啊啊啊!!!!!!
然后稍微不注意就會(huì)出現(xiàn)控制臺(tái)發(fā)生警告,那一坨坨是不是看了都想死....
不過沒關(guān)系,那個(gè)只要調(diào)整一下最后一條和contentView的約束的優(yōu)先級(jí)<調(diào)低一點(diǎn)>(或者瘋狂的用lessThan,greaterThan)就OK了...扯遠(yuǎn)了...
我們的話題是!!這樣很消耗CPU啊啊啊啊.....
你想想:用戶正在用你的APP滾動(dòng)表格,也許他就是想瀏覽一下,就那么滾啊滾,結(jié)果電量掉的嗖嗖的,手機(jī)還發(fā)燙,那么你說你親愛的用戶會(huì)干嘛?給你打個(gè)電話?告訴你:親愛的,你的表格滾起來有點(diǎn)燙手哦~~~~~~呵呵呵呵呵,碰到傲嬌一點(diǎn)的就直接給你卸載了好不好....
好吧..扯了這么多沒用的那么我們來說說解決辦法吧...
那就是:緩存行高..
tableView有這么一個(gè)代理方法:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;
默認(rèn)的情況下每個(gè)Cell會(huì)調(diào)用3次(貌似Xcode版本不一樣這個(gè)值也不盡相同),是不是很驚悚,假如每個(gè)Cell都用自動(dòng)布局,每個(gè)Cell系統(tǒng)都要忙碌的計(jì)算三次,表格能不卡嗎.....
它的原理是這樣的:
1.假如你沒有設(shè)置預(yù)估行高呢,每個(gè)Cell都先計(jì)算一次,然后再計(jì)算你顯示行的高度,一直到Cell能夠填滿你目前的屏幕,同時(shí)更新contentSize這樣你就能滾了,哦,不..你的表格又能愉快的滾動(dòng)了...
2.如果你設(shè)置了預(yù)估行高呢,那么系統(tǒng)會(huì)根據(jù)你設(shè)置的預(yù)估行高計(jì)算一下contentSize;至于你計(jì)算多少次也是根據(jù)你設(shè)置的預(yù)估行高來的,直到填滿你的手機(jī)屏幕,更新contentSize;你要是給太大的預(yù)估行高,超出了預(yù)估的范圍,她會(huì)順序的計(jì)算后面的行高,一直到填滿屏幕...
3.怎么說呢,使用預(yù)估行高在每個(gè)Cell的顯示之前都需要計(jì)算,所以單個(gè)Cell的效率略低,但是整體的效率提高了啊.....
4.所以預(yù)估行高你別瞎給,盡量給的稍微準(zhǔn)點(diǎn)....
言歸正傳.要怎么做呢
在這里我介紹兩個(gè)方法
方法一: 用別人寫好的第三方庫,至于用什么就自行去谷歌或者GitHub上面搜索吧
方法二: 自己緩存.
如果你用MVC開發(fā)呢,就在你的模型屬性中定義一個(gè)專門用來存儲(chǔ)行高的屬性,如果你用MVVM開發(fā)呢,那么就在你的視圖模型中定義一個(gè)存儲(chǔ)行高的屬性(貌似我是在寫廢話......)
然后你再heightForRowAtIndexPath那個(gè)方法里面創(chuàng)建一個(gè)Cell<一定要用alloc/init創(chuàng)建,從緩存池中取會(huì)造成死循環(huán),至于為什么自己去想!!!>,然后你把你的模型數(shù)據(jù)賦值給它,然后重頭戲來了你要調(diào)用一下這個(gè)方法:[self layoutIfNeeded];從而Cell提前計(jì)算約束!提前計(jì)算約束!提前計(jì)算約束!
有了約束你就能獲得最大的Y了,有了最大的Y,行高就緩存上了
在你的Cell里面添加一個(gè)這個(gè)方法
- (CGFloat)calculateRowHeight:(XXModel *)yourModel {
self.model = yourModel;
[self.view layoutIfNeeded];
return CGRectGetMaxY(你最下面控件.frame);
}
最后你再heightForRowAtIndexPath里面返回的行高就是你計(jì)算出來的行高了,這樣只用計(jì)算一次就可以了,并且還作為屬性緩存起來,大大節(jié)省了CPU的開銷....
最后的最后......假如你是ibireme的粉絲的話,他的一篇文章可以拜讀一下,好吧我承認(rèn)寫的比我深刻多了........https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/