YYLable異步渲染在繪圖中的應(yīng)用

方法及關(guān)鍵函數(shù)解釋

static dispatch_queue_t YChartAsyncLayerGetDispalyQueue() {
#define MAX_QUEUE_COUNT 16
    static int queueCount;
    static dispatch_queue_t queues[MAX_QUEUE_COUNT];
    static int32_t counter = 0;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        queueCount = (int)[NSProcessInfo processInfo].activeProcessorCount;
        queueCount = queueCount < 1 ? 1 : queueCount;
        if ( [[UIDevice currentDevice].systemVersion floatValue] >= 8.0 ) {
            for (NSUInteger i = 0 ; i < queueCount; i++) {
                dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0);
                queues[i] = dispatch_queue_create("com.yxw.chart.render", attr);
            }
        }
        else{
            for (NSUInteger i= 0; i < queueCount; i++) {
                queues[i] = dispatch_queue_create("com.yxw.chart.render", DISPATCH_QUEUE_SERIAL);
                dispatch_set_target_queue(queues[i], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
            }
        }
    });
    int32_t cur = OSAtomicIncrement32(&counter);
    if (cur < 0) {
        cur = -cur;
    }
    return queues[cur%queueCount];
}

static dispatch_queue_t YChartAsyncLayerGetReleaseQueue() {
    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
}

iOS8之前和之后設(shè)置線(xiàn)程隊(duì)列優(yōu)先級(jí)及層次體系骑歹,讓不同隊(duì)列中的任務(wù)同步的執(zhí)行時(shí)
iOS8 之前需要?jiǎng)?chuàng)建一個(gè)串行隊(duì)列并設(shè)置和全局隊(duì)列優(yōu)先級(jí)相同: 兩個(gè)線(xiàn)程隊(duì)列分別按照添加順序來(lái)執(zhí)行

 queues[i] = dispatch_queue_create("com.yxw.chart.render", DISPATCH_QUEUE_SERIAL);
                dispatch_set_target_queue(queues[i], dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));

iOS8 之后: QOS_CLASS_USER_INITIATED : 和全局隊(duì)列中的線(xiàn)程優(yōu)先級(jí)相同

 dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_USER_INITIATED, 0);
                queues[i] = dispatch_queue_create("com.yxw.chart.render", attr);

[NSProcessInfo processInfo].activeProcessorCount 獲取當(dāng)前設(shè)備是幾核,創(chuàng)建隊(duì)列數(shù)等于核數(shù)

cell 賦值異步渲染原理

- (void)setDataArray:(NSArray *)dataArray{
    _dataArray = dataArray;
    if (_displaysAsynchronously) {
        [self p_clearContents];
    }
    [self p_setLayoutNeedRedraw];
}

** [self p_clearContents] 為什么會(huì)清空內(nèi)容 ? 清空會(huì)有什么影響 峦树?**
1宪哩、異步渲染當(dāng)前 cell 顯示內(nèi)容清空褂策, 否則會(huì)有錯(cuò)位的現(xiàn)象峭判, 本次異步渲染還未完成時(shí),會(huì)顯示上次的內(nèi)容棍好;
2仗岸、同步渲染是實(shí)時(shí)刷新不會(huì)存在這個(gè)問(wèn)題;
3借笙、因?yàn)槭钱惒戒秩景遣溃援?dāng)快速滾動(dòng)時(shí), 會(huì)看到空白的頁(yè)面业稼;

** [self p_setLayoutNeedRedraw] 異步渲染的原理都在這里**
1盗痒、調(diào)用 YChartAsyncLayer 的 setNeedsDisplay 方法,改變當(dāng)前 cell 保存的隨機(jī)數(shù)低散;
2俯邓、當(dāng)前 cell 新開(kāi)啟一個(gè)異步線(xiàn)程加入到串行隊(duì)列中等待執(zhí)行,每個(gè)線(xiàn)程和一個(gè)隨機(jī)數(shù)對(duì)應(yīng) 谦纱;
3看成、當(dāng)串行隊(duì)列中線(xiàn)程的開(kāi)始渲染 該 cell 時(shí)君编, 先比較該線(xiàn)程對(duì)應(yīng)的 隨機(jī)數(shù)和 cell 當(dāng)前標(biāo)記的 隨機(jī)數(shù)是否相同跨嘉, 如果相同則渲染cell, 如果不相同吃嘿,說(shuō)明 cell 已經(jīng)被復(fù)用祠乃,放棄渲染線(xiàn)程退出梦重;
4、cell 渲染 有三個(gè)步驟 :
(1) willDisplay : 開(kāi)始渲染前亮瓷,移除 layer 持有的動(dòng)畫(huà)琴拧, 在主線(xiàn)程執(zhí)行;
(2) display : 真正開(kāi)始渲染嘱支,在異步線(xiàn)程蚓胸, 渲染過(guò)程中 實(shí)時(shí)判斷是否被取消渲染;
(3) didDisplay : 渲染完成除师,生成一張 image 沛膳,回到主線(xiàn)程,通過(guò)動(dòng)畫(huà)顯示在layer上汛聚;

為什么是 串行線(xiàn)程隊(duì)列 而不是 并行線(xiàn)程隊(duì)列 锹安?

1、當(dāng)快速滾動(dòng)時(shí)創(chuàng)建太多的 線(xiàn)程 卡死現(xiàn)象
**2倚舀、防治數(shù)據(jù)渲染錯(cuò)誤 **:
比如 :
當(dāng)前 cell row=10叹哭, 渲染的線(xiàn)程是 t1 cell數(shù)據(jù) d1
下一次復(fù)用時(shí):
cell row=15, 渲染的線(xiàn)程是 t2 cell數(shù)據(jù) d2
同步線(xiàn)程觸發(fā)時(shí)間及結(jié)束時(shí)間不確定 :
場(chǎng)景1 :
當(dāng) t1 先執(zhí)行后結(jié)束 痕貌,t2 后執(zhí)行先結(jié)束 风罩, 此時(shí) 顯示數(shù)據(jù)為 d1 ;
場(chǎng)景2 :
當(dāng) t2 先執(zhí)行先結(jié)束 ,t1 后執(zhí)行后結(jié)束時(shí)舵稠, 此時(shí) 顯示數(shù)據(jù)為 d1 ;
當(dāng)一次復(fù)用時(shí)有兩個(gè) 線(xiàn)程 4種情況泊交,,當(dāng)有 n 次復(fù)用 最多 2 的 n此方 種情況柱查,顯示錯(cuò)誤概率極高廓俭;

同步的時(shí)候取消時(shí)的邏輯: 最后一次 cell 賦值時(shí)改變了隨機(jī)值,所有復(fù)用該 cell 的同步隊(duì)列中的線(xiàn)程都被取消唉工,所以不會(huì)造成數(shù)據(jù)錯(cuò)亂的現(xiàn)象

最后再回到Y(jié)YLabel

1研乒、YYLabel layer 層

+ (Class)layerClass {
    return [YYTextAsyncLayer class];
}

2、渲染觸發(fā)

- (void)_displayAsync:(BOOL)async {

3淋硝、渲染雹熬,回調(diào)到 leyer.delegate = YYLabel;

- (YYTextAsyncLayerDisplayTask *)newAsyncDisplayTask {
}

4、YYLabel 添加點(diǎn)擊事件: touch 方法去匹配數(shù)據(jù)谣膳,然后重新渲染

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    ........
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
}

參考鏈接

demo;
ibireme/YYText;
iOS 保持界面流暢的技巧;


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末竿报,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子继谚,更是在濱河造成了極大的恐慌烈菌,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芽世,居然都是意外死亡挚赊,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)济瓢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)荠割,“玉大人,你說(shuō)我怎么就攤上這事旺矾∶镳校” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,875評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵箕宙,是天一觀的道長(zhǎng)举反。 經(jīng)常有香客問(wèn)我,道長(zhǎng)扒吁,這世上最難降的妖魔是什么火鼻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,441評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮雕崩,結(jié)果婚禮上魁索,老公的妹妹穿的比我還像新娘。我一直安慰自己盼铁,他們只是感情好粗蔚,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,488評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著饶火,像睡著了一般鹏控。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上肤寝,一...
    開(kāi)封第一講書(shū)人閱讀 51,365評(píng)論 1 302
  • 那天当辐,我揣著相機(jī)與錄音,去河邊找鬼鲤看。 笑死缘揪,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的义桂。 我是一名探鬼主播找筝,決...
    沈念sama閱讀 40,190評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼慷吊!你這毒婦竟也來(lái)了袖裕?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,062評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤溉瓶,失蹤者是張志新(化名)和其女友劉穎急鳄,沒(méi)想到半個(gè)月后谤民,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,500評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡攒岛,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,706評(píng)論 3 335
  • 正文 我和宋清朗相戀三年赖临,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了胞锰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片灾锯。...
    茶點(diǎn)故事閱讀 39,834評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖嗅榕,靈堂內(nèi)的尸體忽然破棺而出顺饮,到底是詐尸還是另有隱情,我是刑警寧澤凌那,帶...
    沈念sama閱讀 35,559評(píng)論 5 345
  • 正文 年R本政府宣布兼雄,位于F島的核電站,受9級(jí)特大地震影響帽蝶,放射性物質(zhì)發(fā)生泄漏赦肋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,167評(píng)論 3 328
  • 文/蒙蒙 一励稳、第九天 我趴在偏房一處隱蔽的房頂上張望佃乘。 院中可真熱鬧,春花似錦驹尼、人聲如沸趣避。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,779評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)程帕。三九已至,卻和暖如春地啰,著一層夾襖步出監(jiān)牢的瞬間愁拭,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,912評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工亏吝, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留敛苇,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,958評(píng)論 2 370
  • 正文 我出身青樓顺呕,卻偏偏與公主長(zhǎng)得像枫攀,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子株茶,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,779評(píng)論 2 354

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

  • 從哪說(shuō)起呢来涨? 單純講多線(xiàn)程編程真的不知道從哪下嘴。启盛。 不如我直接引用一個(gè)最簡(jiǎn)單的問(wèn)題蹦掐,以這個(gè)作為切入點(diǎn)好了 在ma...
    Mr_Baymax閱讀 2,757評(píng)論 1 17
  • *面試心聲:其實(shí)這些題本人都沒(méi)怎么背,但是在上海 兩周半 面了大約10家 收到差不多3個(gè)offer,總結(jié)起來(lái)就是把...
    Dove_iOS閱讀 27,140評(píng)論 30 470
  • 原文地址 http://www.cnblogs.com/kenshincui/p/3983982.html 大家都...
    怎樣m閱讀 1,268評(píng)論 0 1
  • Object C中創(chuàng)建線(xiàn)程的方法是什么技羔?如果在主線(xiàn)程中執(zhí)行代碼,方法是什么卧抗?如果想延時(shí)執(zhí)行代碼藤滥、方法又是什么? 1...
    AlanGe閱讀 1,739評(píng)論 0 17
  • 你信仰童話(huà) 甚至有些固執(zhí)地 幻想自己不會(huì)長(zhǎng)大 直到烏托邦漸漸崩塌 一把利斧 撕碎了所有彩色圖畫(huà) 就像失去空氣的你 ...
    向史而新閱讀 380評(píng)論 0 4