iOS內(nèi)存管理

1, 面試題

1, 使用NSDisplayLink仅淑、NSTimer有什么注意的地方?
2, 介紹下內(nèi)存的幾大區(qū)域线脚?
3, 你對(duì)iOS內(nèi)存管理是怎樣理解的?
4, ARC都幫我們做了什么?
5, weakSelf的原理是怎樣的?
6, autorelease對(duì)象會(huì)在什么時(shí)機(jī)調(diào)用release?
7, 方法里有局部變量, 會(huì)在方法執(zhí)行完之后馬上釋放嗎?

2, timer的探究

我們先從NSTimer開(kāi)始講起

2.1 NSTimer

使用NSTimer最常見(jiàn)的問(wèn)題有兩個(gè): 一個(gè)在后面說(shuō), 另一個(gè)就是循環(huán)引用, 引起循環(huán)引用的原因是: NSTimer中有一個(gè)強(qiáng)引用的target屬性, 持有VC本身, 所以會(huì)形成指針環(huán). 解決的方案有:
1,調(diào)用帶block的方法且配合weakSelf來(lái)達(dá)到弱引用的效果;
2, 使用一個(gè)第三方的中間體來(lái)達(dá)到弱引用的效果(proxy).
接下來(lái)我們先簡(jiǎn)單說(shuō)一下方法1, 然后重點(diǎn)說(shuō)方法2.
調(diào)用帶block的方法且配合weakSelf來(lái)達(dá)到弱引用的效果


使用一個(gè)第三方的中間體來(lái)達(dá)到弱引用的效果(proxy)
這個(gè)方法的原理是這樣的: 創(chuàng)建一個(gè)中間體來(lái)弱引用持有viewController, 從而達(dá)到破壞循環(huán)引用的目的

這個(gè)中間體我們一般稱為proxy, 實(shí)現(xiàn)的方法有兩種: 一種是繼承自NSObject, 另一種方法是繼承自NSProxy. 下面直接po出這兩種方法的實(shí)現(xiàn), 然后比對(duì)效果.
新建一個(gè)工程, 然后分別封裝兩個(gè)proxy類, 并實(shí)現(xiàn)調(diào)用, 代碼截圖如下

封裝的代碼如下, 注意截圖中的提示


上面的代碼就是實(shí)現(xiàn)的全部了, 可能也會(huì)有同學(xué)有疑問(wèn): 為什么不直接在GQProxy00或GQProxy01中實(shí)現(xiàn)test方法呢? 因?yàn)槲覀冊(cè)O(shè)計(jì)這個(gè)proxy中間體就是是為了考慮到以后別的類或者taget也會(huì)使用這個(gè)proxy做中間體, 所以proxy內(nèi)部不寫最終要調(diào)用的方法, 而是返回消息發(fā)送者本身.
接下來(lái)我們說(shuō)一下繼承自NSObject和NSProxy這兩種不同方案的區(qū)別:
1, 繼承自NSObject的中間體使用的是消息發(fā)送的整套機(jī)制, 也就是會(huì)遍歷本身和父類的消息列表, 最終找到方法本身來(lái)進(jìn)行調(diào)用;
2, 繼承自NSProxy的中間體則直接使用消息轉(zhuǎn)發(fā)機(jī)制, 也就是消息發(fā)送機(jī)制的最后一步, 直接將消息轉(zhuǎn)發(fā)出去, 這樣效率更高.
上面的第二點(diǎn)就是NSProxy類的最大用處. 關(guān)于NSProxy可能我們了解的很少, 下面展開(kāi)說(shuō)一下:
NSProxy是啥
NSProxy是一個(gè)跟NSObject同級(jí)的類, 遵守<NSProxy>協(xié)議但不繼承自NSObject; 其本身并沒(méi)有init方法; 當(dāng)使用NSProxy的對(duì)象進(jìn)行方法調(diào)用時(shí), 并不會(huì)去遍歷父類的方法列表, 而是只遍歷本身的方法列表, 如果沒(méi)找到方法實(shí)現(xiàn), 則會(huì)直接將消息轉(zhuǎn)發(fā); 是一個(gè)專門設(shè)計(jì)用來(lái)進(jìn)行消息轉(zhuǎn)發(fā)的類, 相比于一般繼承自NSObject的類, 其轉(zhuǎn)發(fā)消息非常的高效.

剛剛沒(méi)說(shuō)的關(guān)于NStimer的一個(gè)問(wèn)題就是: NStimer定時(shí)器并不能保證時(shí)間精準(zhǔn). 因?yàn)镹Stimer的底層是基于runloop來(lái)實(shí)現(xiàn)的. 實(shí)現(xiàn)的過(guò)程是這樣的: 假如設(shè)置了NStimer時(shí)間間隔為1.0秒, runloop底層有一段計(jì)算時(shí)間的代碼, 當(dāng)runloop每進(jìn)行一次循環(huán)都會(huì)判斷累計(jì)的時(shí)間, 如果累計(jì)時(shí)間>=1.0s, 就會(huì)調(diào)用NStimer的方法. 但其實(shí)runloop每次循環(huán)的時(shí)間都是根據(jù)任務(wù)的不同而有所不同的, 這就是導(dǎo)致不能保證每次累計(jì)的時(shí)間間隔都能精確的控制在1.0s. 所以如果需要精準(zhǔn)的時(shí)間間隔, 應(yīng)該使用GCD, 因?yàn)镚CD是不依賴runloop來(lái)實(shí)現(xiàn)的時(shí)間間隔, 而是依賴內(nèi)核來(lái)實(shí)現(xiàn)的.

2.2 NSDisplayLink

相比于NStimer, NSDisplayLink也可以實(shí)現(xiàn)定時(shí)器功能, 但其可以精準(zhǔn)的實(shí)現(xiàn)60fps幀率的水平, 也就是屏幕刷的幀率. 但其跟NSTimer一樣, 也會(huì)對(duì)taget形成強(qiáng)引用, 引起循環(huán)引用, 而解決的方法跟NStimer一樣, 所以這里就不展開(kāi)說(shuō)了.

接下來(lái)我們講內(nèi)存管理的另一塊知識(shí)點(diǎn): 內(nèi)存布局.

3. 內(nèi)存布局

4, tagged pointer

4.1 簡(jiǎn)介

看下面的介紹

在使用tagged pointer之前, 對(duì)象的存儲(chǔ)是通過(guò)指針來(lái)指向的, 而在tagged pointer之后, 直接把對(duì)象存儲(chǔ)在指針中, 示意圖如下

如何判斷一個(gè)指針是不是tagged pointer? 下面是runtime的源碼

下面我們來(lái)看一個(gè)面試題.

4.2面試題


下面我們直接說(shuō)結(jié)果吧:
第一個(gè)for循環(huán)會(huì)直接報(bào)錯(cuò)崩潰, 而且是地址錯(cuò)誤. 為什么呢? 主要原因有兩個(gè):
1,第一個(gè)跟tagged pointer相關(guān). 在這里, 由于字符串比較長(zhǎng), 所以第一個(gè)name會(huì)被runtime設(shè)置成非tagged pointer, 開(kāi)啟多線程頻繁訪問(wèn)name的時(shí)候, 在底層不停的[_name release]和_name=[name copy]的時(shí)候, 由于沒(méi)有加鎖, 所以可能會(huì)導(dǎo)致不同線程間銷毀原對(duì)象導(dǎo)致野指針錯(cuò)誤;
1, 第二個(gè)跟線程相關(guān), 就是上面提到的多線程讀寫操作.
如果要解決這個(gè)問(wèn)題, 就需要我們?cè)趎ame屬性前加atomic修飾, 而不是nonatomic. 或者對(duì)dispatch_queue進(jìn)行信號(hào)量限制為1.
第二個(gè)for循環(huán)不會(huì)報(bào)錯(cuò), 因?yàn)榈诙€(gè)name的字符串很短, runtime會(huì)將其設(shè)置成tagged pointer, 就不會(huì)存在上面的問(wèn)題, 讀寫值都非常高效.

5, 對(duì)象的內(nèi)存管理

5.1MRC

5.2 copy

一般調(diào)用copy的目的是為了獲得一個(gè)副本對(duì)象, 當(dāng)修改副本對(duì)象或者修改原對(duì)象的時(shí)候, 相互之間不影響. copy可分為深拷貝和淺拷貝, 深拷貝是產(chǎn)生了新的對(duì)象并分配了新的內(nèi)存地址, 淺拷貝則只是拷貝了指針指向原對(duì)象地址, 原對(duì)象和地址都沒(méi)有改變. 下面表格是拷貝的總結(jié):其規(guī)律就是對(duì)象和拷貝返回的對(duì)象不一致時(shí)候, 就需要深拷貝

另外需要注意的兩點(diǎn)是:
1, 用copy修飾的屬性, 編譯器編譯后會(huì)在底層的setter方法內(nèi)部調(diào)用copy方法, 所以一般NSMutabelArray祝迂、NSDictionary等可變對(duì)象都不建議使用copy來(lái)修飾, 否則很容易在后續(xù)代碼中修改值的時(shí)候引起崩潰, 而且xcode也沒(méi)有提示警告;
2, 自定義的類如果想要調(diào)用copy方法, 則必須遵守<NSCopy>協(xié)議并且實(shí)現(xiàn)initWithZone:方法, 并且在方法中寫明需要copy的對(duì)象屬性等.

5.3weak指針的原理

直接總結(jié)如下:
1,當(dāng)一個(gè)對(duì)象被weak指針指向的時(shí)候, runtime會(huì)以這個(gè)對(duì)象的地址值作為key保存到sideTable類中的weak_table散列表中對(duì)應(yīng)的weak指針數(shù)組里;
2, 當(dāng)對(duì)象調(diào)用dealloc方法時(shí)候, 就會(huì)以對(duì)象地址作為key, 從sideTable的weak_table散列表中的weak數(shù)組遍歷逐個(gè)把weak設(shè)置為nil.

6, 自動(dòng)釋放池aotoreleasepool

先看截圖吧



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翰萨,一起剝皮案震驚了整個(gè)濱河市刹缝,隨后出現(xiàn)的幾起案子笛谦,更是在濱河造成了極大的恐慌抱虐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饥脑,死亡現(xiàn)場(chǎng)離奇詭異恳邀,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)灶轰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門谣沸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人笋颤,你說(shuō)我怎么就攤上這事乳附。” “怎么了伴澄?”我有些...
    開(kāi)封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵赋除,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我非凌,道長(zhǎng)举农,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任敞嗡,我火速辦了婚禮颁糟,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘喉悴。我一直安慰自己棱貌,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開(kāi)白布粥惧。 她就那樣靜靜地躺著键畴,像睡著了一般最盅。 火紅的嫁衣襯著肌膚如雪突雪。 梳的紋絲不亂的頭發(fā)上起惕,一...
    開(kāi)封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天,我揣著相機(jī)與錄音咏删,去河邊找鬼惹想。 笑死,一個(gè)胖子當(dāng)著我的面吹牛督函,可吹牛的內(nèi)容都是我干的嘀粱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼辰狡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼锋叨!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起宛篇,我...
    開(kāi)封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤娃磺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后叫倍,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體偷卧,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年吆倦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了听诸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡蚕泽,死狀恐怖晌梨,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赛糟,我是刑警寧澤派任,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站璧南,受9級(jí)特大地震影響掌逛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜司倚,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一豆混、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧动知,春花似錦皿伺、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春妒穴,著一層夾襖步出監(jiān)牢的瞬間宋税,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來(lái)泰國(guó)打工讼油, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留杰赛,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓矮台,卻偏偏與公主長(zhǎng)得像乏屯,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瘦赫,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

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