? Runloop work distribution (Runloop任務(wù)分發(fā))是ASDK使用的比較核心的一種技術(shù)铛碑。從我測(cè)試的情況來(lái)看鳖敷,Runloop任務(wù)分發(fā)的時(shí)候帕翻,有優(yōu)先處理數(shù)據(jù)邏輯等绍些,而UI的更新會(huì)延遲膘滨,即使UI更新發(fā)生在邏輯任務(wù)前昌妹。
? 我創(chuàng)建了一個(gè)名為RWD_Test的工程,測(cè)試代碼如下:
(1)
? 在下面的for循環(huán)前修改testView的frame握截,run起來(lái)后飞崖,發(fā)現(xiàn)testView frame的改變發(fā)生在for循環(huán)完成之后。
? 再看谨胞,我們把代碼修改一下:
(2)
? 在for循環(huán)后再加一行改變testView frame的代碼固歪,run起來(lái)后,testView frame改變還是發(fā)生在for循環(huán)之后胯努,只是testView frame直接改變?yōu)閒or循環(huán)后設(shè)置的frame牢裳,并沒(méi)有改變兩次。
? 我們?cè)侔汛a修改一下叶沛,把for循環(huán)放到子線程執(zhí)行:
(3)
?把for循環(huán)邏輯放到子線程后蒲讯,run起來(lái)后,testView frame馬上改變了灰署。
?以上的現(xiàn)象我們看到了判帮。那原理是啥呢?
? iOS 的顯示系統(tǒng)是由 VSync 信號(hào)驅(qū)動(dòng)的溉箕,VSync 信號(hào)由硬件時(shí)鐘生成晦墙,每秒鐘發(fā)出 60 次。iOS 圖形服務(wù)接收到 VSync 信號(hào)后肴茄,會(huì)通過(guò) IPC 通知到 App 內(nèi)晌畅。App 的 Runloop 在啟動(dòng)后會(huì)注冊(cè)對(duì)應(yīng)的 CFRunLoopSource 通過(guò) mach_port 接收傳過(guò)來(lái)的時(shí)鐘信號(hào)通知,隨后 Source 的回調(diào)會(huì)驅(qū)動(dòng)整個(gè) App 的動(dòng)畫(huà)與顯示寡痰。
?Core Animation 在 RunLoop 中注冊(cè)了一個(gè) Observer踩麦,監(jiān)聽(tīng)了 BeforeWaiting 和 Exit 事件。這個(gè) Observer 的優(yōu)先級(jí)是 2000000氓癌,低于常見(jiàn)的其他 Observer谓谦。當(dāng)一個(gè)觸摸事件到來(lái)時(shí),RunLoop 被喚醒贪婉,App 中的代碼會(huì)執(zhí)行一些操作反粥,比如創(chuàng)建和調(diào)整視圖層級(jí)、設(shè)置 UIView 的 frame疲迂、修改 CALayer 的透明度才顿、為視圖添加一個(gè)動(dòng)畫(huà);這些操作最終都會(huì)被 CALayer 捕獲尤蒿,并通過(guò) CATransaction 提交到一個(gè)中間狀態(tài)去(CATransaction 的文檔略有提到這些內(nèi)容郑气,但并不完整),如果這段時(shí)間有多次更新腰池,最新的會(huì)覆蓋之前的改變尾组,如現(xiàn)象(2)忙芒。當(dāng)上面所有操作結(jié)束后,RunLoop 即將進(jìn)入休眠(或者退出)時(shí)讳侨,關(guān)注該事件的 Observer 都會(huì)得到通知呵萨。這時(shí) CA 注冊(cè)的那個(gè) Observer 就會(huì)在回調(diào)中,把所有的中間狀態(tài)合并提交到 GPU 去顯示跨跨;如果此處有動(dòng)畫(huà)潮峦,CA 會(huì)通過(guò) DisplayLink 等機(jī)制多次觸發(fā)相關(guān)流程,現(xiàn)象(1)證明了這一點(diǎn)勇婴。
? 雖然UI的改變和其他的邏輯處理沒(méi)有優(yōu)先級(jí)這個(gè)說(shuō)法忱嘹,但是系統(tǒng)還是做了區(qū)分,表現(xiàn)出UI更新的優(yōu)先級(jí)顯得低些耕渴。所以在開(kāi)發(fā)過(guò)程中拘悦,把一些任務(wù)量大的任務(wù)放到子線程去處理,有利于提升性能(現(xiàn)象(3))萨螺!
? 此外窄做,我還發(fā)現(xiàn)愧驱,runloop在每分鐘內(nèi)都會(huì)自動(dòng)啟動(dòng)一次慰技,即使任何事情都沒(méi)發(fā)生。
git:https://github.com/GongZiYuan/RWD_Test