1. 程式人生 > >nonatomic, retain,weak,strong用法詳解

nonatomic, retain,weak,strong用法詳解

strong weak

strong與weak是由ARC新引入的物件變數屬性 ARC引入了新的物件的新生命週期限定,即零弱引用。如果零弱引用指向的物件被deallocated的話,零弱引用的物件會被自動設定為nil。
@property(strong) MyClass *myObject; 相當於@property(retain) MyClass *myObject;
@property(weak) MyOtherClass *delegate; 相當於@property(assign) MyOtherClass *delegate;
強引用與弱引用的廣義區別:
  強引用也就是我們通常所講的引用,其存亡直接決定了所指物件的存亡。如果不存在指向一個物件的引用,並且此物件不再顯示列表中,則此物件會被從記憶體中釋放。
  弱引用除了不決定物件的存亡外,其他與強引用相同。即使一個物件被持有無數個若引用,只要沒有強引用指向他,那麼其還是會被清除。沒辦法,還是 “強哥” 有面子。
簡單講strong等同retain
weak比assign多了一個功能,當物件消失後自動把指標變成nil,好處不言而喻。
__weak, __strong 用來修飾變數,此外還有 __unsafe_unretained, __autoreleasing 都是用來修飾變數的。
__strong 是預設的關鍵詞。
__weak 聲明瞭一個可以自動 nil 化的弱引用。
__unsafe_unretained 宣告一個弱應用,但是不會自動nil化,也就是說,如果所指向的記憶體區域被釋放了,這個指標就是一個野指標了。
__autoreleasing 用來修飾一個函式的引數,這個引數會在函式返回的時候被自動釋放。

之前寫一個基於地理位置應用程式的時候無法讓應用程式開啟定位功能,在.h檔案裡面,我定義的屬性是這樣的:

@property(weak, nonatomic) CLLocationManager *locationManager;
後來,我將上面這句話改為:

@property(nonatomic, retain) CLLocationManager *locationManager;
就可以了。

接下來,就詳細得介紹一下nonatomic, retain,weak,strong
在我們開發iOS程式時,常常會遇到:
property 和synthesize,以前很懶沒有仔細去理解,只是看了看別人寫的書,覺得挺容易的(在這裡我不得不說,現在很多本土出的土書,尤其是早期的2009年,寫的是真亂,誤人子弟),所以今天有時間,自己試驗了一番,希望和大家討論。property,他可以提供的功能有:提供成員變數的訪問方法的宣告、控制成員變數的訪問許可權、控制多執行緒時成員變數的訪問環境 )。property不但可以在interface,在協議[url=]protocol[/url]
 .和類別[url=]category[/url]中也可以使用.synthesize的理解是:實現property所宣告的方法的定義。其實說直白就像是:property聲明瞭一些成員變數的訪問方法 ,synthesize則定義了由property宣告的方法。他們之前的對應關係是  property 宣告方法 ----------》 標頭檔案中申明的方法 synthesize定義方法---------》Cpp檔案中定義的方法
不過這裡還有有一點細微的差別,後面我會講到。
先講property大家都知道:@property(attribute1 , attribute2, ...])是@property的他的官方表達方式,所以看到attribute1, attribute2,你就應該懂的, 他的用法不是很簡單。下面就對他的屬性列表進行分類介紹:下面對屬性列表進行一下簡單的介紹,後續會用程式碼來解釋。1.可讀性:readonly 、readwrite@property(readwrite,....) valueType value;
這個屬性是變數的預設屬性,就是如果你(readwrite and readonly都沒有使用,那麼你的變數就是readwrite屬性),通過加入readwrite屬性你的變數就會有get方法,和set方法。property(readonly,...) valueType value;這個屬性變數就是表明變數只有可讀方法,也就是說,你只能使用它的get方法。2,assign,setter方法直接賦值,不進行任何retain操作,為了解決原型別與環循引用問題3,retain,setter方法對引數進行release舊值再retain新值,所有實現都是這個順序4,copy,setter方法進行Copy操作,與retain處理流程一樣,先舊值release,再Copy出新的物件,retainCount為1。這是為了減少對上下文的依賴而引入的機制。5,nonatomic,非原子性訪問,不加同步,多執行緒併發訪問會提高效能。注意,如果不加此屬性,則預設是兩個訪問方法都為原子型事務訪問。鎖被加到所屬物件例項級.所以 不加nonatomic對與多執行緒是安全的 。 
其實他們都可以用程式碼表示:1.nonatomic 和 atomic@property(nonatomic ) NSObject* test1;
@synthesize test1;上面兩句程式碼,表示我們對test1的訪問,是非多執行緒安全的。@property(atomic) NSObject* test1;
@synthesize test1;上面兩句程式碼,表示我們對test1的訪問,是多執行緒安全的。其實也就是在講該成員變數放到互斥程式碼中,例如,下面進行加鎖。[_internal lock]; // lock using an object-level lock 
id result = [[value retain] autorelease]; 
[_internal unlock]; 
return result;

就如上面所說 ,這兩個屬性,是出於對多執行緒條件下 ,對test1的訪問安全。如果你的程式的成員變數不存在安全問題,用nonatomic 就好,因為這樣不要在訪問是進行互斥,效率更高。2. readonly 、readwrite (注,後續過程我們都會加入nonatomic 屬性,因為它是十分普遍的)2.1 readonly@property(nonatomic  ,readonly) NSObject* test1;
@synthesize test1;上面的兩句程式碼,objc編輯器將會為我們翻譯為:@property(nonatomic  ,readonly) NSObject* test1; 等同-(NSObject*)test1;
@synthesize test1;等同-(NSObject*)test1{ return test1;}2.2 readwrite 
@property(nonatomic  ,readwrite ) NSObject* test1;
@synthesize test1;上面的兩句程式碼,objc編輯器將會為我們翻譯為:@property(nonatomic  ,readwrite ) NSObject* test1; 等同-(NSObject*)test1;
-(void)settest1(NSObject* other);@synthesize test1;等同-(NSObject*)test1{ return test1;}-(void)settest1(NSObject* other);
{ test1 = other;} 這裡要說明一下, readonly 、readwrite 這兩個屬性他們的真正價值,不是提供成員變數訪問介面,而是控制 成員變數的訪問許可權。所以要抓住他們真正價值。3. assign@property(nonatomic  ,assign) NSObject* test1;@synthesize test1;上面兩句:objc編輯器將會翻譯如下:@property(nonatomic  ,assign) NSObject* test1;等同 -(void)settest1(NSObject* other);@synthesize test1;-(void)settest1(NSObject* other);等同
{ test1 = other;}
4. retain@property(nonatomic  ,retain) NSObject* test1;
@synthesize test1; objc編輯器翻譯如: @property(nonatomic  ,retain) NSObject* test1;等同-(NSObject*)test1;
-(void)settest1(NSObject* other); @synthesize test1;
-(NSObject*)test1{ return test1;}-(void)settest1(NSObject* other) {    if (test1!= other)    {                   [test1release];                   test1= [otherretain];     }}5. copy@property(nonatomic  ,copy) NSObject* test1;
@synthesize test1; objc編輯器將翻譯如: @property(nonatomic  ,copy) NSObject* test1;
-(NSObject*)test1;
-(void)settest1(NSObject* other); @synthesize test1;
-(NSObject*)test1{ return test1;}-(void)settest1(NSObject* other);
{     if (test1!=other) { 
        [test1release]; 
        test1= [othercopy]; 
    }
}對於Copy屬性有一點要主要,被定義有copy屬性的物件必須要符合NSCopying協議,並且你還必須實現了-(id)copyWithZoneNSZone*)zone該方法
程式碼才是王道:都是一些簡單程式碼用例//為了更具有普遍性,我選擇用自定義物件testObj /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//testObj .h
@interface testObj : NSObject<NSCopying>{
    
}
@end
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//testObj .m-(id)copyWithZoneNSZone *)zone
{
    testObj* pObj = [[testObj allocWithZone:zone] init];
    return pObj;
}
@end
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////testApp是包含多個testObj 物件指標//testApp .h
@interface testApp :
{
    testObj*  test1;
    testObj*  _test2;
}

@property(nonatomic , retain) NSObject* test1;
@property(nonatomic , copy) NSObject* test2;/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//[email protected] test1;@synthesize test2 = _test2;//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@synthesize test2 = _test2; //對這裡要特別主要一下,這裡可以看作是一種別名機制,這點和前面類比的C++標頭檔案和Cpp檔案不同。
例如對於setter函式,objc編輯器將會按如下方式翻譯如果是@synthesize _test2;setter函式將是這種形式:-(void)set_test2(NSObject*); //注意中間的下劃線寫成@synthesize test = _test2;setter函式將是這種形式:
-(void)settest2(NSObject*);// _test2 被 test2替換了
可以看出這種別名機制,感覺是規範書寫(其實更像是規範Objc的書寫,大家可以看看官方文件中,成員變數都是前面帶下滑線的(如_test2),所以才搞了這樣一個別名規範程式碼中的書寫)
//下面是一個功能函式,-(void )test{test1 = [[testObj alloc]init];// test1  retainCount  =1;

//下面有三種對test2操作方法: _test2 = test1; //這裡是將test1的指標賦值給_test2指標,注意,並沒有呼叫test2的setter方法 ,所以test retainCount  = 1、 test2 retainCount  = 0; self.test2 = test1;  //這裡呼叫test2的Copy方法,因此這是test retainCount  = 1、 test2 retainCount  = 1;   test2   = test1; //這段程式碼系統將會提示出錯說test2沒有定義。因為這裡編譯器認為是一條賦值表示式,將test2看作是一個成員變數,而在我們的testApp 中是沒有這個成員變數的,這裡要區別我們所說的別名,別名機制可以看作是在呼叫setter或者getter函式才會起作用,而這裡只是一個簡單的賦值,也就出現未定義的錯誤。如果沒有理解,你就記住要呼叫setter或者getter函式,就用"self.成員變數"這種形式就行了.
//我們把  test2   = test1這行程式碼註釋掉,保證程式繼續執行    [test1 release];  // 釋放test1 ,test1 retainCount  = 0;
    
    [test2 release]; // 釋放test2 ,test2 retainCount  = 0;
}@end

相關推薦

nonatomic, retain,weak,strong用法

strong weak strong與weak是由ARC新引入的物件變數屬性 ARC引入了新的物件的新生命週期限定,即零弱引用。如果零弱引用指向的物件被deallocated的話,零弱引用的物件會被自動設定為nil。 @property(strong) MyClass *

object-c學習:@property 屬性中 assign,nonatomic,retainstrong,weak的區別

strong關鍵字與retain關似,用了它,引用計數自動+1,用例項更能說明一切 @property (nonatomic, strong) NSString *string1;    @property (nonatomic, strong) NSString *string2;   有這樣兩個屬性

JavaScript中return的用法

style 返回 www log tle blog 意思 charset fun 1、定義:return 從字面上的看就是返回,官方定義return語句將終止當前函數並返回當前函數的值,可以看下下面的示例代碼: <!DOCTYPE html><html l

SVN trunk(主線) branch(分支) tag(標記) 用法和詳細操作步驟

trac load mar span 必須 最可 objc copy 右鍵 原文地址:http://blog.csdn.net/vbirdbest/article/details/51122637 使用場景: 假如你的項目(這裏指的是手機客戶端項目)的某個版本(例如1.0

js 定時器用法——setTimeout()、setInterval()、clearTimeout()、clearInterval()

ntb 幫助 .get tint num 用法 -c 函數 tel 在js應用中,定時器的作用就是可以設定當到達一個時間來執行一個函數,或者每隔幾秒重復執行某段函數。這裏面涉及到了三個函數方法:setInterval()、setTimeout()、clearI

selenium用法

key url enc element api code 需要 int question selenium用法詳解 selenium主要是用來做自動化測試,支持多種瀏覽器,爬蟲中主要用來解決JavaScript渲染問題。 模擬瀏覽器進行網頁加載,當requests,url

C# ListView用法

ont 結束 server 發生 匹配 鼠標 之前 小圖標 order 一、ListView類 1、常用的基本屬性: (1)FullRowSelect:設置是否行選擇模式。(默認為false) 提示:只有在Details視圖該屬性才有意義

linux cp命令參數及用法---linux 復制文件命令cp

linux file linux cp命令參數及用法詳解---linux 復制文件命令cp [root@Linux ~]# cp [-adfilprsu] 來源檔(source) 目的檔(destination)[root@linux

Python數據類型方法簡介一————字符串的用法

python 字符串連接 字符串用法 符串是Python中的重要的數據類型之一,並且字符串是不可修改的。 字符串就是引號(單、雙和三引號)之間的字符集合。(字符串必須在引號之內,引號必須成對)註:單、雙和三引號在使用上並無太大的區別; 引號之間可以采取交叉使用的方式避免過多轉義;

C# ListView用法(轉)

分組 創建 cti 排列 checkbox 定義 com 程序 erl 一、ListView類 1、常用的基本屬性: (1)FullRowSelect:設置是否行選擇模式。(默認為false) 提示:只有在Details視圖該屬性才有

java中的instanceof用法

定義 xtend print 繼承 interface 參數 保留 如果 ack   instanceof是Java的一個二元操作符(運算符),也是Java的保留關鍵字。它的作用是判斷其左邊對象是否為其右邊類的實例,返回的是boolean類型的數據。用它來判斷某個對象是否是

@RequestMapping 用法

同時 get() turn example track find 說明 tex -h 簡介: @RequestMapping RequestMapping是一個用來處理請求地址映射的註解,可用於類或方法上。用於類上,表示類中的所有響應請求的方法都是以該地址作為父路徑。

Css中路徑data:image/png;base64的用法 (轉載)

javascrip base64編碼 asc cda 文件的 color 情況 ont 背景圖片 大家可能註意到了,網頁上有些圖片的src或css背景圖片的url後面跟了一大串字符,比如: background-image:url(data:image/png;bas

global用法

global 在函數內傳遞參數1、global一般用在函數內,將外部變量參數傳遞至函數內部,用法為:<?php $name = "why"; function changeName(){ global $name; $name = "what";

java中靜態代碼塊的用法—— static用法

super關鍵字 了解 裝載 static關鍵字 super 屬於 註意 lock 自動 (一)java 靜態代碼塊 靜態方法區別一般情況下,如果有些代碼必須在項目啟動的時候就執行的時候,需要使用靜態代碼塊,這種代碼是主動執行的;需要在項目啟動的時候就初始化,在不創建對象的

<!CDATA[]]用法

引號 ica lap 用法 bsp mar ret message eight 所有 XML 文檔中的文本均會被解析器解析。 只有 CDATA 區段(CDATA section)中的文本會被解析器忽略。 PCDATA PCDATA 指的是被解析的字符數據(Parsed

Es6 Promise 用法

set 問題 得到 math clas promise 回調 console spa Promise是什麽?? 打印出來看看 console.dir(Promise) 這麽一看就明白了,Promise是一個構造函數,自己身上有all、reject、r

[轉] angular2-highcharts用法

ppc tip option select sel nbsp 用法詳解 points ttr 1、 使用npm安裝angular2-highcharts npm install angular2-highcharts --save 2、主模塊中引入 app.module.t

常見<meta>的基本用法

代碼 簡介 clas 元素 word spa wid min mpat <meta charset="utf-8"> 定義與name 屬性相關的信息,使用 utf-8編碼方式編譯字符 <meta http-equiv="X-UA-Compatible" c

oracle中的exists 和not exists 用法

sdn ref 用法詳解 html nbsp e30 .net tail sin oracle中的exists 和not exists 用法詳解 http://blog.csdn.net/zhiweianran/article/details/7868894oracle