[toc]
Runloop
- Runloop本質(zhì)上是一個(gè)實(shí)現(xiàn)“閑”等待的do-while循環(huán)锋叨。
- 用來讓App中的線程在有任務(wù)的時(shí)候讓進(jìn)入處理狀態(tài),沒有任務(wù)的時(shí)候進(jìn)入休閑狀態(tài),以此節(jié)省CPU資源,提升App性能陷寝。
- Runloop對(duì)象創(chuàng)建后,會(huì)保存在一個(gè)全局dictionary內(nèi)其馏,以線程作為key凤跑,runloop對(duì)象作為value。runloop和線程是一一對(duì)應(yīng)的關(guān)系尝偎。一個(gè)Runloop對(duì)象里面包含了多個(gè)RunLoopMode饶火,每個(gè)RunLoopMode中又包含source0鹏控、source1致扯、timer、observer当辐;每次Runloop啟動(dòng)只能指定一個(gè)mode抖僵。如果需要切換mode,只能重啟runloop缘揪,目的是為了分隔不同的數(shù)據(jù)souce/timer/observer,保證互不受影響耍群。source0處理應(yīng)用層事件义桂,source1處理系統(tǒng)層事件,timer是時(shí)間觸發(fā)器(接收消息的port固定)蹈垢,NSTimer就是基于timer的慷吊,observer是消息循環(huán)中的一個(gè)監(jiān)聽器,隨時(shí)通知外部當(dāng)前RunLoop的運(yùn)行狀態(tài)曹抬。
- 在實(shí)際開發(fā)過程中溉瓶,主要涉及的場(chǎng)景有:線程保活(分擔(dān)主線程壓力)谤民、延遲加載圖片(保證流暢性)堰酿、NSTimer在界面滑動(dòng)時(shí)停止回調(diào)解決、檢測(cè)應(yīng)用卡頓
擴(kuò)展
- 子線程默認(rèn)沒有runloop张足,需要手動(dòng)通過懶加載的方式創(chuàng)建触创,并運(yùn)行起來
- NSTimer使用之前需要注冊(cè)到runloop中,其回調(diào)是基于runloop的为牍,如果runloop中執(zhí)行的任務(wù)耗時(shí)過長(zhǎng)哼绑,那么就只能等到下個(gè)時(shí)間點(diǎn)回調(diào),因此導(dǎo)致NSTimer不太準(zhǔn)確碉咆。
- observer監(jiān)聽的狀態(tài)有
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 進(jìn)入RunLoop
kCFRunLoopBeforeTimers = (1UL << 1), // 即將開始Timer處理
kCFRunLoopBeforeSources = (1UL << 2), // 即將開始Source處理
kCFRunLoopBeforeWaiting = (1UL << 5), // 即將進(jìn)入休眠
kCFRunLoopAfterWaiting = (1UL << 6), //從休眠狀態(tài)喚醒
kCFRunLoopExit = (1UL << 7), //退出RunLoop
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
- 應(yīng)用卡頓監(jiān)聽的是停留在其中一個(gè)狀態(tài)的時(shí)間過長(zhǎng)
AutoReleasePool
- 自動(dòng)釋放池是一種內(nèi)存自動(dòng)回收機(jī)制凌那,是由AutoReleasePoolPage連接實(shí)現(xiàn)的雙向列表。
- 自動(dòng)釋放池可以延時(shí)釋放對(duì)象吟逝。正常情況下變量會(huì)在超出作用域后立即release帽蝶,加入釋放池后,會(huì)等到runloop休眠 或者 超出作用域后release块攒。
多線程
響應(yīng)者鏈
消息響應(yīng)機(jī)制
消息轉(zhuǎn)發(fā)機(jī)制
App在pre-main階段的活動(dòng)
動(dòng)態(tài)庫 和 靜態(tài)庫 區(qū)別
iOS內(nèi)存管理
OC對(duì)象內(nèi)存布局
WKWebview 如何實(shí)現(xiàn)js交互
內(nèi)存空間 (堆和棧的區(qū)別)
主要分為 五大區(qū)
- 棧區(qū) Stack
- 堆區(qū) Head
- 全局/靜態(tài)區(qū)
- 文字/常量區(qū)
- 代碼區(qū) code
- 棧區(qū)
特點(diǎn):是一塊連續(xù)的內(nèi)存區(qū)域励稳,先進(jìn)后出,后進(jìn)先出(方便用來保存/恢復(fù)現(xiàn)場(chǎng)調(diào)用)囱井;從高地址到低地址分配驹尼;
用于存放臨時(shí)創(chuàng)建的局部變量;指針都在棧區(qū)(指針指向的堆區(qū)的地址);
一般情況下,地址0x7xxxx是棧區(qū)庞呕;
優(yōu)點(diǎn): 編譯器自動(dòng)分配釋放新翎,不會(huì)產(chǎn)生內(nèi)存碎片,使用起來快速高效
缺點(diǎn): 內(nèi)存大小有限制住练,數(shù)據(jù)不靈活(主線程大小只有1MB地啰,其他線程512KB)
- 堆區(qū)
特點(diǎn):是一塊不連續(xù)的內(nèi)存區(qū)域,先進(jìn)先出原則讲逛;從低地址向高地址分配
當(dāng)需要訪問堆中內(nèi)存時(shí)亏吝,一般需要先通過對(duì)象讀取到棧區(qū)的指針地址,然后通過指針訪問堆區(qū)盏混。
地址0x6xxxx是堆區(qū)蔚鸥;
優(yōu)點(diǎn): 靈活方便
缺點(diǎn): 速度較棧慢惜论,容易產(chǎn)生內(nèi)存碎片
- 全局區(qū)
特點(diǎn): 編譯時(shí)分配,一般以0x1xxxx開頭止喷;
程序運(yùn)行過程中馆类,此內(nèi)存數(shù)據(jù)一直存在,程序結(jié)束后釋放弹谁;
分為 未初始化 和 已初始化的兩個(gè)區(qū)間蹦掐;
包含全局變量 和 靜態(tài)變量,全局變量指向的變量值可以被修改僵闯;靜態(tài)變量時(shí)static修飾的變量卧抗,包含靜態(tài)局部變量和全局變量。
- 常量區(qū)
特點(diǎn): 編譯時(shí)分配鳖粟,程序結(jié)束后由系統(tǒng)釋放社裆;
存放 已經(jīng)使用了的,且沒有指向的字符串常量向图;
- 代碼區(qū)
編譯時(shí)分配泳秀,主要用于存放程序運(yùn)行時(shí)的代碼(二進(jìn)制)
內(nèi)存泄漏
- 申請(qǐng)的內(nèi)存空間使用完畢后未回收。
- 多次內(nèi)存泄漏榄攀,不斷消耗內(nèi)存空間嗜傅,最終會(huì)導(dǎo)致崩潰。
- 原因:(1)檩赢、循環(huán)引用:NSTimer直接使用 (2)吕嘀、循環(huán)引用:strong修飾的Delegate (3)、循環(huán)引用:Block (4)贞瞒、CF對(duì)象(C語言偶房,ARC只支持OC)未手動(dòng)釋放 (5)、被全局變量直接或間接持有军浆,未斷開
- 檢測(cè)方案 (1)棕洋、開發(fā)階段:靜態(tài)分析(Analyze)(2)、開發(fā)階段:動(dòng)態(tài)分析方法(Instrument的Leaks) (3)乒融、測(cè)試階段:使用自定義工具(或三方工具檢測(cè)內(nèi)存泄漏掰盘,如 哆啦A夢(mèng))
- Analyze 檢測(cè)的類型
1、邏輯錯(cuò)誤 2赞季、聲明錯(cuò)誤 3愧捕、內(nèi)存泄漏 4、引用Api錯(cuò)誤
- Leaks 檢測(cè)原理
直接搜索內(nèi)存區(qū)間進(jìn)行檢查是否有引用碟摆,沒有引用的卻還在使用的內(nèi)存就是泄漏
- 三方檢測(cè)
MLeaksFinder: 當(dāng)一個(gè)controller被pop或者dismiss掉后晃财,其view和subView也會(huì)很快被釋放掉,3秒后查看是否還存在典蜕,如果存在就是內(nèi)存泄漏
優(yōu)點(diǎn): 無侵入性断盛,可支持白名單
FBRetainCycleDetector : 查找以該對(duì)象為根節(jié)點(diǎn)的強(qiáng)引用樹中有沒有循環(huán)引用。
渲染原理(離屏渲染)
深拷貝/淺拷貝(copy/multableCopy)
屬性修飾符的作用
各種線程鎖
NotificationCenter實(shí)現(xiàn)原理
KVO實(shí)現(xiàn)原理
Window的作用
runtime
- 如何添加屬性
- category愉舔,method 的實(shí)現(xiàn)機(jī)制钢猛,class的載入過程