IOS 圖形性能優(yōu)化錦集(2)

趁著剛剛上班還有空的時間繼續(xù)寫一寫博客,今天剛上班就被告知產(chǎn)品6.2已經(jīng)設(shè)計好了侥蒙,明天開發(fā)暗膜,然后看了下需求,瞬間又淚奔了鞭衩,又是一輪奮力地去干学搜。
好了,前話就說這么多论衍,我們繼續(xù)我們的圖形性能優(yōu)化了瑞佩,值得一說的就是上一篇文章編寫離屏渲染那段不太清晰,還是需要找個時間去修改一下坯台,讓各位小伙伴更明白炬丸。

6 使用后臺繪制

當(dāng)你的應(yīng)用存在的繪圖部分并不是那么流暢的時候,你可以去檢驗一下是否你的 drawRect: 就是影響你應(yīng)用性能的瓶頸蜒蕾,那么稠炬,你可以將這段繪制代碼放到后臺去做。但是在你這么做之前咪啡,檢查是不是有其他方法來解決首启,比如、考慮使用 core animation layers 或者預(yù)先渲染圖片而不去做 Core Graphics 繪制撤摸∶銎拢可以看看 Florian 對在真機(jī)上圖像性能測量的帖子,或者可以看看來自 UIKit 工程師 Andy Matuschak 對個各種方式的權(quán)衡的評論愁溜。
我們或多或少都聽過后臺繪制疾嗅,但是實質(zhì)上我們該怎么做呢?思路如下:

將原本打算繪制的視圖用一個 UIImageView 來代替冕象,當(dāng)所有繪制操作完成后渲染成一張 UIImage 代承,
然后來替換到 UIImageView 中去。在繪制的方法中渐扮,使用UIGraphicsBeginImageContextWithOptions
來取代 UIGraphicsGetCurrentContext论悴。

talk is cheap掖棉,show me the code。下面膀估,我就一步一步教小伙伴們?nèi)绾稳プ觥?/p>

1.首先創(chuàng)建一個 ASynchronousDrawView 類繼承 UIView

ASynchronousDrawView.h
@interface ASynchronousDrawView : UIView

@end

ASynchronousDrawView.m
@interface ASynchronousDrawView()
@property (nonatomic , weak) UIImageView *imageView;
@end

2.然后在 initWithFrame: 方法中去建立好 UIImageView

ASynchronousDrawView.m
@implementation ASynchronousDrawView
- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        UIImageView *imageView = [[UIImageView alloc] init];
        imageView.frame = self.bounds;
        imageView.backgroundColor = [UIColor whiteColor];
        [self addSubview:imageView];
        self.imageView = imageView;
}
    return self;
}

3.好了幔亥,接下來就是我們的繪制方法,我下面代碼只是一個演示察纯,并不是說這段代碼很耗時帕棉,小伙伴們要根據(jù)情況來用喔。

- (void)asynchronousDrawComplete:(void(^)(UIImage *))complete {
// 異步繪制饼记,在繪制方法中香伴,使用 UIGraphicsBeginImageContextWithOptions 來取代 UIGraphicsGetCurrentContext
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        // 第三個參數(shù)傳入0 ,設(shè)備的主屏幕的 scale 將被自動傳入具则,這將使圖片在普通設(shè)備和 retina 屏幕上都有良好的表現(xiàn)即纲。[UIScreen mainScreen].scale
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(self.frame.size.width, self.frame.size.height), true, 0);
        // 實例畫圖代碼(耗時的繪制應(yīng)放在這里)
        UIBezierPath *bezier = [UIBezierPath bezierPath];
        [[UIColor redColor] setFill];
        [bezier addArcWithCenter:CGPointMake(self.frame.size.width * 0.5, self.frame.size.height * 0.5) radius:40 startAngle:0 endAngle:M_PI * 2 clockwise:true];
        [bezier fill];
        // 將繪制轉(zhuǎn)換成圖片
        UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
        // 關(guān)閉圖片上下文
        UIGraphicsEndImageContext();
    
        dispatch_async(dispatch_get_main_queue(), ^{
           // 繪制操作完成,將圖片傳出去
            complete(image); 
        });
    });
}

4.調(diào)用后臺繪制方法來替換 UIImageViewUIImage

   // 開始異步繪制
    __weak typeof(self) weakSelf = self;
    [self asynchronousDrawComplete:^(UIImage *image) {
        weakSelf.iconView.image = image;
    }];

當(dāng)然博肋,我們調(diào)用到 block 的小伙伴低斋,記得,防止循環(huán)引用喔匪凡。

以上就是后臺繪制的方法實現(xiàn)了拔稳,根據(jù)這個方法我們可以將 drawRect: 方法中耗時的繪制分離出來,讓我們的性能進(jìn)一步提高锹雏。除了在后臺自己調(diào)度繪制代碼,以也可以試試看使用 CALayerdrawsAsynchronously 屬性术奖。然而你需要精心衡量這樣做的效果礁遵,因為有時候它能使繪制加速,有時候卻適得其反采记。


7 使用 NSCache 來為緩存 UITableView 中的 SectionHeadView

我們在使用 UITableView 的時候可能要為每一組 Section 都得加一個一個 HeadView佣耐,然后就會用到
*-(UIView )tableView:viewForHeaderInSection: 這個方法,小伙伴們通常都會這么調(diào)用

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *secHeadView  = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    return secHeadView;
}

但是通過打下斷點的方法我們就知道唧龄,當(dāng)我們滾動 tableView兼砖,每當(dāng)滾動到每一組的 headView 的時候就會調(diào)用一次,上面方法就會產(chǎn)生一個 secHeadView 對象既棺,這樣做無疑是浪費(fèi)我們的內(nèi)存讽挟,能少創(chuàng)建對象才是皇道呀。

那么我們該怎么優(yōu)化這樣需求呢丸冕,沒錯耽梅,我們需要把視圖緩存,那么就不需要每次滾動的時候就去重新創(chuàng)建一次了胖烛,然后我們在適當(dāng)?shù)臅r候?qū)⒕彺驷尫诺粞劢悖迅嗟膬?nèi)存騰出來诅迷。但是,這里又衍生了一個問題众旗,緩存方法有很多罢杉,例如用 NSArrayNSDictionary 等這些容器對象贡歧,或者用 NSPointerFunctions 這些指針容器類滩租。但是,我們在這里選擇 NSCache艘款。
為什么選擇NSCache持际?

NSCache 用法跟 NSDictionary 一樣,可以調(diào)用 objectForKey:哗咆、setObject:forkey:和 removeObjectForkey蜘欲。
但是 NSCache 有一些特性是被低估了,比如其多線程的安全性晌柬,小伙伴們可以在任何線程不加鎖的情況下修改 NSCache姥份。
NSCache 還沒設(shè)計為能與符合<NSDiscardableContent>協(xié)議的對象整合,這不僅能在應(yīng)用運(yùn)行的時候提供
自動緩存管理年碘,甚至在應(yīng)用暫停的時候也有用澈歉。意思當(dāng)你的內(nèi)存吃緊的時候,系統(tǒng)會幫你釋放 NSCache 內(nèi)的對象屿衅,
而且埃难,這是相當(dāng)安全的行為。

還是來代碼讓小伙伴們精神精神吧涤久。

1.創(chuàng)建 NSCache 對象

self.scHeadcache = [[NSCache alloc] init];

2.在*-(UIView )tableView:viewForHeaderInSection: 檢驗一下涡尘。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIView *view;
    if (![self.scHeadcache objectForKey:@(section)]) {
        view  = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
    }
    else {
        view = [self.scHeadcache objectForKey:@(section)];
    }

    return view;
}

當(dāng)然這個 NSCache 對象也是會占內(nèi)存的,所以我們會在適當(dāng)?shù)臅r候把它釋放出去响迂,那什么是適當(dāng)?shù)臅r候呢考抄,當(dāng)然是用戶不再對著頁面感興趣的時候啦。

@end


好了蔗彤,今天先寫這么多川梅,還得認(rèn)認(rèn)真真的擼代碼,新的一年然遏,大家加油喔贫途。

心如止水,奮力前行

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末待侵,一起剝皮案震驚了整個濱河市潮饱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌诫给,老刑警劉巖香拉,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啦扬,死亡現(xiàn)場離奇詭異,居然都是意外死亡凫碌,警方通過查閱死者的電腦和手機(jī)扑毡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來盛险,“玉大人瞄摊,你說我怎么就攤上這事】嗑颍” “怎么了换帜?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鹤啡。 經(jīng)常有香客問我惯驼,道長,這世上最難降的妖魔是什么递瑰? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任祟牲,我火速辦了婚禮,結(jié)果婚禮上抖部,老公的妹妹穿的比我還像新娘说贝。我一直安慰自己,他們只是感情好慎颗,可當(dāng)我...
    茶點故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布乡恕。 她就那樣靜靜地躺著,像睡著了一般俯萎。 火紅的嫁衣襯著肌膚如雪傲宜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天讯屈,我揣著相機(jī)與錄音,去河邊找鬼县习。 笑死涮母,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的躁愿。 我是一名探鬼主播叛本,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼彤钟!你這毒婦竟也來了来候?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤逸雹,失蹤者是張志新(化名)和其女友劉穎营搅,沒想到半個月后云挟,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡转质,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年园欣,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片休蟹。...
    茶點故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡沸枯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出赂弓,到底是詐尸還是另有隱情绑榴,我是刑警寧澤,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布盈魁,位于F島的核電站翔怎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏备埃。R本人自食惡果不足惜姓惑,卻給世界環(huán)境...
    茶點故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望按脚。 院中可真熱鬧于毙,春花似錦、人聲如沸辅搬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽堪遂。三九已至介蛉,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間溶褪,已是汗流浹背币旧。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留猿妈,地道東北人吹菱。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像彭则,于是被迫代替她去往敵國和親鳍刷。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,465評論 2 348

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,743評論 25 707
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫俯抖、插件输瓜、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 12,059評論 4 62
  • Swift版本點擊這里歡迎加入QQ群交流: 594119878最新更新日期:18-09-17 About A cu...
    ylgwhyh閱讀 25,322評論 7 249
  • 美白丸, 如何祛痘芹缔?不要熬夜坯癣,一定不要熬夜!平常吃清淡的最欠,要少化妝示罗,做好皮膚清潔,不要用卸妝油或者油脂性的護(hù)膚品芝硬。...
    LHo閱讀 667評論 0 3
  • 沒有人是任性的蚜点,沒有人是挑剔的“枰酰可能是知道得多绍绘,選擇多了。就開始對比迟赃,一些及格的看不上了陪拘,想要及格線以上的。漸漸的...
    AlexWong樣閱讀 678評論 0 0