ARC

来源:http://www.cnblogs.com/Mr-Lin/archive/2016/06/26/5618799.html
-Advertisement-
Play Games

ARC是什麼 ARC是iOS 5推出的新功能,全稱叫 ARC(Automatic Reference Counting)。簡單地說,就是代碼中自動加入了retain/release,原先需要手動添加的用來處理記憶體管理的引用計數的代碼可以自動地由編譯器完成了。 該機能在 iOS 5/ Mac OS X ...


ARC是什麼

ARC是iOS 5推出的新功能,全稱叫 ARC(Automatic Reference Counting)。簡單地說,就是代碼中自動加入了retain/release,原先需要手動添加的用來處理記憶體管理的引用計數的代碼可以自動地由編譯器完成了。

該機能在 iOS 5/ Mac OS X 10.7 開始導入,利用 Xcode4.2 可以使用該機能。簡單地理解ARC,就是通過指定的語法,讓編譯器(LLVM 3.0)在編譯代碼時,自動生成實例的引用計數管理部分代碼。有一點,ARC並不是GC,它只是一種代碼靜態分析(Static Analyzer)工具。

變化點

通過一小段代碼,我們看看使用ARC前後的變化點。

 1 @interface NonARCObject : NSObject {    
 2     NSString *name;    
 3 }    
 4 -(id)initWithName:(NSString *)name;    
 5 @end    
 6    
 7 @implementation NonARCObject    
 8 -(id)initWithName:(NSString *)newName {    
 9     self = [super init];    
10     if (self) {    
11         name = [newName retain];    
12     }    
13     return self;    
14 }    
15    
16 -(void)dealloc {    
17     [name release];    
18     [Super dealloc];    
19 }    
20 @end    
 1 @interface ARCObject : NSObject {    
 2     NSString *name;    
 3 }    
 4 -(id)initWithName:(NSString *)name;    
 5 @end    
 6    
 7 @implementation ARCObject    
 8 -(id)initWithName:(NSString *)newName {    
 9     self = [super init];    
10     if (self) {    
11         name = newName;    
12     }    
13     return self;    
14 }    
15 @end    
我們之前使用Objective-C中記憶體管理規則時,往往採用下麵的準則
  •    生成對象時,使用autorelease
  •    對象代入時,先autorelease後再retain
  •    對象在函數中返回時,使用return [[object retain] autorelease];

而使用ARC後,我們可以不需要這樣做了,甚至連最基礎的release都不需要了。

 

使用ARC的好處

使用ARC有什麼好處呢?

  •    看到上面的例子,大家就知道了,以後寫Objective-C的代碼變得簡單多了,因為我們不需要擔心煩人的記憶體管理,擔心記憶體泄露了
  •    代碼的總量變少了,看上去清爽了不少,也節省了勞動力
  •    代碼高速化,由於使用編譯器管理引用計數,減少了低效代碼的可能性

 

不好的地方

  •    記住一堆新的ARC規則 — 關鍵字及特性等需要一定的學習周期
  •    一些舊的代碼,第三方代碼使用的時候比較麻煩;修改代碼需要工數,要麼修改編譯開關

關於第二點,由於 XCode4.2 中預設ARC就是 ON 的狀態,所以編譯舊代碼的時候往往有"Automatic Reference Counting Issue"的錯誤信息。

 

這個時候,可以將項目編譯設置中的“Objectice-C Auto Reference Counteting”設為NO。如下所示。

 

 

如果只想對某個.m文件不適應ARC,可以只針對該類文件加上 -fno-objc-arc 編譯FLAGS,如下圖。

 

 

ARC基本規則

  •     retain, release, autorelease, dealloc由編譯器自動插入,不能在代碼中調用
  •     dealloc雖然可以被重載,但是不能調用[super dealloc]

由於ARC並不是GC,並需要一些規則讓編譯器支持代碼插入,所以必須清楚清楚了這些規則後,才能寫出健壯的代碼。

 

Objective-C對象

ObjectiveC中的對象,有強參照(Strong reference)和弱參照(Weak reference)之分,當需要保持其他對象的時候,需要retain以確保對象引用計數加1。對象的持有者(owner)只要存在,那麼該對象的強參照就一直存在。

對象處理的基本規則是

  •     只要對象的持有者存在(對象被強參照),那麼就可以使用該對象
  •     對象失去了持有者後,即被破棄

 

強參照 (Strong reference)

 

 
(s1)

firstName作為”natsu”字元串對象的最初持有者,是該NSString類型對象的Strong reference。

(s2)

這裡將firstName代入到aName中,即aName也成為了@”natsu”字元串對象的持有者,對於該對象,aName也是Strong reference。

(s3)

這裡,改變firstName的內容。生成新的字元串對象”maki”。這時候firstName成為”maki”的持有者,而@”natsu”的持有者只有aName。每個字元串對象都有各自的持有者,所以它們都在記憶體中都存在。

(s4)

追加新的變數otherName, 它將成為@”maki”對象的另一個持有者。即NSString類型對象的Strong reference。

(s5)

將otherName代入到aName,這時,aName將成為@”maki”字元串對象的持有者。而對象@”natsu”已經沒有持有者了,該對象將被破棄。

 

弱參照 (Weak reference)

接下來我們來看看弱參照 (Weak reference) 的使用方式。

 

 

(w1)

與強參照方式同樣,firstName作為字元串對象@”natsu”的持有者存在。即是該NSString類型對象的Strong reference。

(w2)

使用關鍵字__weak,聲明弱參照weakName變數,將firstName代入。這時weakName雖然參照@”natsu”,但仍是Weak reference。即weakName雖然能看到@”natsu”,但不是其持有者。

(w3)

firstName指向了新的對象@”maki”,成為其持有者,而對象@”natsu”因為沒有了持有者,即被破棄。同時weakName變數將被自動代入nil。

 

引用關鍵字

ARC中關於對象的引用參照,主要有下麵幾關鍵字。使用strong, weak, autoreleasing限定的變數會被隱式初始化為nil。

 

  • __strong

變數聲明預設都帶有__strong關鍵字,如果變數什麼關鍵字都不寫,那麼預設就是強參照。

 

  • __weak

上面已經看到了,這是弱參照的關鍵字。該概念是新特性,從 iOS 5/ Mac OS X 10.7 開始導入。由於該類型不影響對象的生命周期,所以如果對象之前就沒有持有者,那麼會出現剛創建就被破棄的問題,比如下麵的代碼。

1 NSString __weak *string = [[NSString alloc] initWithFormat:@"First Name: %@", [self firstName]];    
2 NSLog(@"string: %@", string); //此時 string為空  

如果編譯設定OS版本 Deployment Target 設定為這比這低的版本,那麼編譯時將報錯(The current deployment target does not support automated __weak references),這個時候,我們可以使用下麵的 __unsafe_unretained。

弱參照還有一個特征,即當參數對象失去所有者之後,變數會被自動付上nil (Zeroing)。

 

  • __unsafe_unretained

該關鍵字與__weak一樣,也是弱參照,與__weak的區別隻是是否執行nil賦值(Zeroing)。但是這樣,需要註意變數所指的對象已經被破棄了,地址還還存在,但記憶體中對象已經沒有了。如果還是訪問該對象,將引起「BAD_ACCESS」錯誤。

 

  • __autoreleasing

該關鍵字使對像延遲釋放。比如你想傳一個未初始化的對像引用到一個方法當中,在此方法中實例化此對像,那麼這種情況可以使用__autoreleasing。他被經常用於函數有值參數返回時的處理,比如下麵的例子。

 1 - (void) generateErrorInVariable:(__autoreleasing NSError **)paramError {    
 2     ....    
 3     *paramError = [[NSError alloc] initWithDomain:@"MyApp" code:1 userInfo:errorDictionary];    
 4 }    
 5    
 6 ....    
 7 {    
 8     NSError *error = nil;    
 9     [self generateErrorInVariable:&error];    
10     NSLog(@"Error = %@", error);    
11 }    

又如函數的返回值是在函數中申請的,那麼希望釋放是在調用端時,往往有下麵的代碼。

 1 -(NSString *)stringTest    
 2 {    
 3     NSString *retStr = [NSString stringWithString:@"test"];    
 4    
 5     return [[retStr retain] autorelease];    
 6 }    
 7    
 8 // 使用ARC    
 9    
10 -(NSString *)stringTest    
11 {    
12     __autoreleasing NSString *retStr = [NSString alloc] initWithString:@"test"];    
13    
14     return retStr;    

即當方法的參數是id*,且希望方法返回時對象被autoreleased,那麼使用該關鍵字。

 

總結

今天,我們看到了基本的ARC使用規則

  •     代碼中不能使用retain, release, retain, autorelease
  •     不重載dealloc(如果是釋放對象記憶體以外的處理,是可以重載該函數的,但是不能調用[super dealloc])
  •     不能使用NSAllocateObject, NSDeallocateObject
  •     不能在C結構體中使用對象指針
  •     id與void *間的如果cast時需要用特定的方法(__bridge關鍵字)
  •     不能使用NSAutoReleasePool、而需要@autoreleasepool塊
  •     不能使用“new”開始的屬性名稱 (如果使用會有下麵的編譯錯誤”Property’s synthesized getter follows Cocoa naming convention for returning ‘owned’ objects”)

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • HTML5簡介 HTML5是HTML的最新修訂標準。2014年10月29日,萬維網聯盟(W3C)宣佈,經過8年的努力,HTML5標準規範制定完成。 HTML5的設計目的是在移動設備上使用多媒體。 HTML5簡單易學。 http://hovertree.com/menu/html5/ 什麼是HTML5 ...
  • × 目錄 [1]定義 [2]應用場景 [3]轉為布爾[4]實例方法 前面的話 布爾值Boolean類型可能是三種包裝對象Number、String和Boolean中最簡單的一種。Number和String對象擁有大量的實例屬性和方法,Boolean卻很少。從某種意義上說,為電腦設計程式就是與布爾值 ...
  • 1、HTML5不支持或不贊成使用的標簽 <acronym>——定義只取首字母的縮寫,HTML5 不支持。使用<abbr>定義縮寫代替,其中title 屬性可用於在滑鼠指針移動到元素上時顯示出縮寫的完整版本,堅持寫上title,這樣對瀏覽器和搜索引擎都比較友好。 <applet>——定義嵌入的 app ...
  • 在不同瀏覽器查看代碼效果可謂是家常便飯,所以用不同快捷鍵打開相應瀏覽器可以大大提高工作效率。工欲善其事,必先利其器啊,沒設置看文章吧,非常簡單。 ...
  • CSS樣式規範 1.類選擇器 2.標簽選擇器 3.id選擇器 4.CSS樣式的子選擇器 類選擇器 1.必背的固定結構,成為CSS樣式標記。所有的樣式都可以寫成CSS樣式的標記中 <style type="text/css"> </style> 2. type=“text/css” 意思是聲明這個標記 ...
  • 通過javascript進行UTF 8編碼 javascript的字元集: javascript程式是使用 字元集編寫的。 是`ASCII Latin 1 ECMAScript3 Unicode2.1 ECMAScript5 Unicode3`及後續版本。所以,我們編寫出來的javascript程式 ...
  • 關於這三個移動端的事件,詳細的資料網上一搜一大片,我就不浪費時間了 1.移動端長按事件 說明:通過定時器模擬長按事件,這個例子基於jQuery,【ele】是要長按的元素; 2.移動端上下左右滑動事件 說明:具體原理一搜一堆,這裡的具體例子,拷貝就能用;我的學習方式是,不管什麼原理之類的,先要做的就是 ...
  • 原生JS選擇器有getElementById、getElementsByName、getElementsByTagName和getElementsByClassName這四個,下麵我就一個一個介紹這四個選擇器的用法。 1.getElementById(通過ID獲取元素) 用法:document.ge ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...