一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - IOS - IOS中內存管理那些事

IOS中內存管理那些事

2020-12-28 11:18iOS開發網 IOS

這篇文章主要介紹了IOS中內存管理那些事的相關資料,需要的朋友可以參考下

objective-c 和 swift 語言的內存管理方式都是基于引用計數「reference counting」的,引用計數是一個簡單而有效管理對象生命周期的方式。引用計數分為手動引用計數「arc: automaticreference counting」和自動引用計數「mrc: manual reference counting」,現在都是用 arc 了,但是我們還是很有必要了解 mrc。

1. 引用計數的原理是什么?

當我們創建一個新對象時,他的引用計數為1;

當有一個新的指針指向這個對象時,他的引用計數就加1;

當對象關聯的某個指針不再指向他時,他的引用計數就減1;

當對象的引用計數為0時,說明此對象不再被任何指針指向,這時我們就可以將對象銷毀,回收內存。

由于引用計數簡單有效,除了 objective-c 語言外,microsoft 的 com「component object model」、c++11(基于引用計數的智能指針 share_prt)等語言也提供了基于引用計數的內存管理方式。

IOS中內存管理那些事

舉個例子:

新建工程,xcode 默認開啟的是 arc,我們這里針對「appdelegate.m」文件使用 mrc,進行以下配置:

選擇目標工程,然后在「build phases」的「compile sources」下的「appdelegate.m」文件配置編譯器參數「compiler flags」值為「-fno-objc-arc」

IOS中內存管理那些事

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
- (bool)application:(uiapplication *)application didfinishlaunchingwithoptions:(nsdictionary *)launchoptions {
  nsobject *objo = [nsobject new];
  nslog(@"reference count: %lu", (unsigned long)[objo retaincount]); // 1
  nsobject *objb = [objo retain];
  nslog(@"reference count: %lu", (unsigned long)[objo retaincount]); // 2
  [objo release];
  nslog(@"reference count: %lu", (unsigned long)[objo retaincount]); // 1
  [objo release];
  nslog(@"reference count: %lu", (unsigned long)[objo retaincount]); // 1
  
  [objo setvalue:nil forkey:@"test"]; // 僵尸對象,向野指針發送消息會報錯(exc_bad_access)
  
  return yes;
}

 

IOS中內存管理那些事

xcode 默認不會監控僵尸對象,這里我們配置開啟他,然后就可以看到具體的跟蹤信息了:

IOS中內存管理那些事

 

IOS中內存管理那些事

也可以通過選擇「product」下的「profile」來打開「instruments」工具集。然后選擇「zombies」,再單擊右下角的「choose」按鈕進入檢測界面,這時點擊左上角的「record」紅色圓點按鈕開始檢測。

IOS中內存管理那些事

 

IOS中內存管理那些事

1.1 上面例子,為什么最后一次通過 retaincount 獲取的值為1,而不是為0呢?

因為該對象的內存已經被回收,我們向一個被回收的對象發送 retaincount 消息,他的輸出結果是不確定的,如果該對象所占內存被復用了,那么就可能造成程序異常崩潰。

而且當最后一次執行 release 時,系統已經知道馬上要回收內存了,就沒必要再將 retaincount 減1,因為不管減不減1,該對象都會被回收,回收后他所在內存區域(包括 retaincount 值)就沒有意義了。不將retaincount 減1變為0,可以減少一次內存操作,加快對象的回收。

 

1.2 什么是僵尸對象、野指針、空指針呢?

僵尸對象:所占用內存已經被回收的對象,僵尸對象不能再使用。

野指針:指向僵尸對象(不可用內存)的指針,給野指針發送消息會報錯(exc_bad_access)。

空指針:沒有指向任何對象的指針(存儲的是 nil、null),給空指針發送消息不會報錯;空指針的一個經典使用場景就是在開發中獲取服務器 api 數據時,轉換野指針為空指針,避免發送消息報錯。

 

2. 為什么需要引用計數?

從上面簡單例子,我們還看不出引用計數真正的用處,因為該對象的生命周期只是在一個方法內。在真實的應用場景中,我們在方法內使用臨時對象,通常不需要修改他的引用計數,只需要在方法返回前銷毀對象就可以了。

然而,引用計數真正派上用場的場景是在面向對象的程序設計架構中,用于對象之間傳遞和共享數據。

 

舉個例子:

假如對象 a 生成了一個對象 o,需要調用對象 b 的某個方法,將對象 o 作為參數傳遞過去。

在沒有引用計數的情況下,一般內存管理的原則是「誰申請誰釋放」,那么對象 a 就需要在對象 b 不再需要對象 o 的時候,將對象 o 銷毀。但對象 b 可能臨時用一下對象 o,也可以覺得他重要,將他設置為自己的一個成員變量,在這種情況下,什么時候銷毀對象 o 就成了一個難題了。

IOS中內存管理那些事

對于以上情況有兩種做法:

(1)對象 a 在調用完對象 b 的某個方法之后,馬上銷毀參數對象 o,然后對象 b 需要將對象 o 復制一份,生成另一個對象 o2,同時自己來管理對象 o2 的生命周期。但是這種做法有一個很大的問題,就是他帶來更多的內存申請、復制、釋放的工作。本來可以復用的對象,因為不方便管理他的生命周期,就簡單地把他銷毀,又重新構造一份一樣的,實在太影響性能。

(2)對象 a 只負責生成對象 o,之后就由對象 b 負責完成對象 o 的銷毀工作。如果對象 b 只是臨時用一下對象 o,就可以用完后馬上銷毀,如果對象 b 需要長時間使用對象 o,就不銷毀他。這種做法看似解決了對象復制的問題,但是他強烈依賴于 a 和 b 兩個對象的配合,代碼維護者需要明確地記住這種編程約定。而且,由于對象 o 的生成和釋放在不同對象中,使得他的內存管理代碼分散在不同對象中,管理起來也很費勁。如果這個時候情況更加復雜一些,例如對象 b 需要再向對象 c 傳遞參數對象 o,那么這個對象在對象 c 中又不能讓對象 c 管理。所以這種方法帶來的復雜度更高,更加不可取。

IOS中內存管理那些事

引用計數的出現很好地解決這個問題,在參數對象 o 的傳遞過程中,哪些對象需要長時間使用他,就把他的引用計數加1,使用完就減1。所有對象遵守這個規則,對象的生命周期管理就可以完全交給引用計數了。我們也可以很方便地享受到共享對象帶來的好處。

2.1 什么是循環引用「reference cycles」問題,怎么解決呢?

引用計數這種內存管理方式雖然簡單,但有一個瑕疵就是他不能自動解決循環引用的問題。

舉個例子:

對象 a 和對象 b 相互引用對方作為自己的成員變量,只有當自己銷毀時,才將自己的成員變量的引用計數減1,因為對象 a 和對象 b 的銷毀相互依賴,這樣就造成我們所說的循環引用問題了。

循環引用會導致即使外界已經沒有任何指針能夠訪問他們了,但是他們所占資源仍然無法釋放的情況。

IOS中內存管理那些事

解決循環引用問題主要有兩種方法:

(1)明確知道哪里存在循環引用,合理時機主動斷開環中的一個引用,使得對象得以回收。這種方法不常用,因為他依賴開發人員自己手工顯式控制,相當于回到以前「誰申請誰釋放」的內存管理年代。

(2)使用弱引用「weak reference」,「weak」「__weak」類型,這種方法常用。弱引用雖然持有對象,但是并不增加他的引用計數。弱引用的一個經典使用場景就是委托代理「delegate」協議模式。

 

2.2 xcode 中有什么工具可以檢測循環引用嗎?

在 xcode 中有「instruments」工具集可以很方便地檢測循環引用。

舉個例子:

 

?
1
2
3
4
5
6
7
8
- (void)viewdidload {
  [super viewdidload];
  
  nsmutablearray *marrfirst = [nsmutablearray array];
  nsmutablearray *marrsecond = [nsmutablearray array];
  [marrfirst addobject:marrsecond];
  [marrsecond addobject:marrfirst];
}

可以選擇「product」下的「profile」來打開「instruments」工具集。

IOS中內存管理那些事

然后選擇「leaks」,再單擊右下角的「choose」按鈕進入檢測界面,這時點擊左上角的「record」紅色圓點按鈕開始檢測。

IOS中內存管理那些事

 

IOS中內存管理那些事

 

IOS中內存管理那些事

 

IOS中內存管理那些事

 

IOS中內存管理那些事

3. core foundation 對象的內存管理

arc 是編譯器特性,他不是運行時特性,更不是垃圾回收器「gc」。

arc 能夠解決 ios 開發中90%的內存管理問題,但是另外10%的內存管理問題是需要開發人員自己處理的,這主要是與底層 core foundation 對象交互的部分,底層 core foundation 對象由于不在 arc 的管理下,所以需要自己維護這些對象的引用計數。

實際上 core foundation 對象使用的 cfretain 和 cfrelease 方法,可以認為與 objective-c 對象的 retain 和 release 方法等價,所以我們可以以 mrc 的方式進行類似管理。

 

3.1 在 arc 中,通過什么方式可以把 core foundation 對象轉換為 objective-c 對象呢?

轉換的過程,其實是告訴編譯器,對象的引用計數如何調整。

這里我們可以使用橋接「bridge」相關關鍵字來進行轉換工作,以下是這些(雙下劃線)關鍵字的說明:

(1)__bridge:只做類型轉換,不修改相關對象的引用計數,原來的 core foundation 對象在不用時,需要調用 cfrelease 方法。

(2)__bridge_retained:類型轉換后,將相關對象的引用計數加1,原來的 core foundation 對象在不用時,需要調用 cfrelease 方法。

(3)__bridge_transfer:類型轉換后,將相關對象的引用計數交給 arc 管理,原來的 core foundation 對象在不用時,不需要調用 cfrelease 方法。

 

我們根據具體的業務邏輯,合理使用上面的三種轉換關鍵字,就可以解決core foundation 對象 與 objective-c 對象相對轉換的問題了。

延伸 · 閱讀

精彩推薦
  • IOSiOS開發之視圖切換

    iOS開發之視圖切換

    在iOS開發中視圖的切換是很頻繁的,獨立的視圖應用在實際開發過程中并不常見,除非你的應用足夠簡單。在iOS開發中常用的視圖切換有三種,今天我們將...

    執著丶執念5272021-01-16
  • IOSiOS中MD5加密算法的介紹和使用

    iOS中MD5加密算法的介紹和使用

    MD5加密是最常用的加密方法之一,是從一段字符串中通過相應特征生成一段32位的數字字母混合碼。對輸入信息生成唯一的128位散列值(32個字符)。這篇文...

    LYSNote5432021-02-04
  • IOSiOS中UILabel實現長按復制功能實例代碼

    iOS中UILabel實現長按復制功能實例代碼

    在iOS開發過程中,有時候會用到UILabel展示的內容,那么就設計到點擊UILabel復制它上面展示的內容的功能,也就是Label長按復制功能,下面這篇文章主要給大...

    devilx12792021-04-02
  • IOSiOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)

    iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和

    這篇文章主要介紹了iOS中滑動控制屏幕亮度和系統音量(附加AVAudioPlayer基本用法和Masonry簡單使用)的相關資料,需要的朋友可以參考下...

    CodingFire13652021-02-26
  • IOSiOS開發技巧之狀態欄字體顏色的設置方法

    iOS開發技巧之狀態欄字體顏色的設置方法

    有時候我們需要根據不同的背景修改狀態欄字體的顏色,下面這篇文章主要給大家介紹了關于iOS開發技巧之狀態欄字體顏色的設置方法,文中通過示例代碼...

    夢想家-mxj8922021-05-10
  • IOSiOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果

    這篇文章主要介紹了iOS自定義UICollectionViewFlowLayout實現圖片瀏覽效果的相關資料,需要的朋友可以參考下...

    jiangamh8882021-01-11
  • IOSiOS實現控制屏幕常亮不變暗的方法示例

    iOS實現控制屏幕常亮不變暗的方法示例

    最近在工作中遇到了要將iOS屏幕保持常亮的需求,所以下面這篇文章主要給大家介紹了關于利用iOS如何實現控制屏幕常亮不變暗的方法,文中給出了詳細的...

    隨風13332021-04-02
  • IOS詳解iOS中多個網絡請求的同步問題總結

    詳解iOS中多個網絡請求的同步問題總結

    這篇文章主要介紹了詳解iOS中多個網絡請求的同步問題總結,小編覺得挺不錯的,現在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧...

    liang199111302021-03-15
主站蜘蛛池模板: 国产精品久久久久久久久齐齐 | 果冻传媒在线视频播放观看 | 丝袜足控免费网站xx动漫漫画 | 午夜dj影院在线视频观看完整 | 三星w699 | 国产成人亚洲精品91专区高清 | 美女机机对机机的视频(免费) | 性俄罗斯xxxxxhd | 成人亚洲欧美日韩在线观看 | 国产成人精品综合在线观看 | 国产在线精品香蕉综合网一区 | 色妞女女女女女bbbb | 男人免费视频 | 日比免费视频 | 肉大捧一进一出视频免费播放 | 秋霞一级成人欧美理论 | 99久久国产综合精品1尤物 | 日韩欧美一区二区三区中文精品 | m3u8久久国产精品影院 | 日产国产精品亚洲系列 | 九九99九九精彩 | 互换娇妻爽文100系列小说 | 国产人妖xxxxx免费看 | 3d动漫免费 | 免费观看大片毛片 | 日韩理论片| 国产成人久久久精品一区二区三区 | 日本视频免费在线观看 | 精品国产福利在线观看一区 | 免费一区在线观看 | 色婷婷综合缴情综六月 | 成年人黄色录像 | 草久热 | 小寡妇好紧进去了好大看视频 | 高中生放荡日记高h娜娜 | 国产成人精品视频午夜 | 91免费永久国产在线观看 | 俺去俺来也www色官网免费的 | 亚洲欧洲淘宝天堂日本 | 精品免费视在线观看 | 男人午夜免费视频 |