nonatomic, retain,weak,strong用法详解
strong weak
strong與weak是由ARC新引入的對(duì)象變量屬性 ARC引入了新的對(duì)象的新生命周期限定,即零弱引用。如果零弱引用指向的對(duì)象被deallocated的話,零弱引用的對(duì)象會(huì)被自動(dòng)設(shè)置為nil。?
@property(strong) MyClass *myObject; 相當(dāng)于@property(retain) MyClass *myObject;?
@property(weak) MyOtherClass *delegate; 相當(dāng)于@property(assign) MyOtherClass *delegate;?
強(qiáng)引用與弱引用的廣義區(qū)別:??強(qiáng)引用也就是我們通常所講的引用,其存亡直接決定了所指對(duì)象的存亡。如果不存在指向一個(gè)對(duì)象的引用,并且此對(duì)象不再顯示列表中,則此對(duì)象會(huì)被從內(nèi)存中釋放。
??弱引用除了不決定對(duì)象的存亡外,其他與強(qiáng)引用相同。即使一個(gè)對(duì)象被持有無數(shù)個(gè)若引用,只要沒有強(qiáng)引用指向他,那麼其還是會(huì)被清除。沒辦法,還是 “強(qiáng)哥” 有面子。
?
簡(jiǎn)單講strong等同retainweak比assign多了一個(gè)功能,當(dāng)對(duì)象消失后自動(dòng)把指針變成nil,好處不言而喻。
?
__weak, __strong 用來修飾變量,此外還有 __unsafe_unretained, __autoreleasing 都是用來修飾變量的。__strong 是缺省的關(guān)鍵詞。
__weak 聲明了一個(gè)可以自動(dòng) nil 化的弱引用。
__unsafe_unretained 聲明一個(gè)弱應(yīng)用,但是不會(huì)自動(dòng)nil化,也就是說,如果所指向的內(nèi)存區(qū)域被釋放了,這個(gè)指針就是一個(gè)野指針了。
__autoreleasing 用來修飾一個(gè)函數(shù)的參數(shù),這個(gè)參數(shù)會(huì)在函數(shù)返回的時(shí)候被自動(dòng)釋放。
?
?
?
之前寫一個(gè)基于地理位置應(yīng)用程序的時(shí)候無法讓應(yīng)用程序打開定位功能,在.h文件里面,我定義的屬性是這樣的:
?
@property(weak, nonatomic) CLLocationManager *locationManager;
后來,我將上面這句話改為:
就可以了。
接下來,就詳細(xì)得介紹一下nonatomic, retain,weak,strong
在我們開發(fā)iOS程序時(shí),常常會(huì)遇到:
property 和synthesize,以前很懶沒有仔細(xì)去理解,只是看了看別人寫的書,覺得挺容易的(在這里我不得不說,現(xiàn)在很多本土出的土?xí)?#xff0c;尤其是早期的2009年,寫的是真亂,誤人子弟),所以今天有時(shí)間,自己試驗(yàn)了一番,希望和大家討論。property,他可以提供的功能有:提供成員變量的訪問方法的聲明、控制成員變量的訪問權(quán)限、控制多線程時(shí)成員變量的訪問環(huán)境 )。property不但可以在interface,在協(xié)議[url=]protocol[/url]?.和類別[url=]category[/url]中也可以使用.synthesize的理解是:實(shí)現(xiàn)property所聲明的方法的定義。其實(shí)說直白就像是:property聲明了一些成員變量的訪問方法 ,synthesize則定義了由property聲明的方法。他們之前的對(duì)應(yīng)關(guān)系是??property 聲明方法 ----------》 頭文件中申明的方法 synthesize定義方法---------》Cpp文件中定義的方法
不過這里還有有一點(diǎn)細(xì)微的差別,后面我會(huì)講到。
先講property大家都知道:@property(attribute1 , attribute2, ...])是@property的他的官方表達(dá)方式,所以看到attribute1, attribute2,你就應(yīng)該懂的, 他的用法不是很簡(jiǎn)單。下面就對(duì)他的屬性列表進(jìn)行分類介紹:下面對(duì)屬性列表進(jìn)行一下簡(jiǎn)單的介紹,后續(xù)會(huì)用代碼來解釋。1.可讀性:readonly 、readwrite@property(readwrite,....) valueType value;這個(gè)屬性是變量的默認(rèn)屬性,就是如果你(readwrite and readonly都沒有使用,那么你的變量就是readwrite屬性),通過加入readwrite屬性你的變量就會(huì)有g(shù)et方法,和set方法。property(readonly,...) valueType value;這個(gè)屬性變量就是表明變量只有可讀方法,也就是說,你只能使用它的get方法。2,assign,setter方法直接賦值,不進(jìn)行任何retain操作,為了解決原類型與環(huán)循引用問題3,retain,setter方法對(duì)參數(shù)進(jìn)行release舊值再retain新值,所有實(shí)現(xiàn)都是這個(gè)順序
4,copy,setter方法進(jìn)行Copy操作,與retain處理流程一樣,先舊值release,再Copy出新的對(duì)象,retainCount為1。這是為了減少對(duì)上下文的依賴而引入的機(jī)制。
5,nonatomic,非原子性訪問,不加同步,多線程并發(fā)訪問會(huì)提高性能。注意,如果不加此屬性,則默認(rèn)是兩個(gè)訪問方法都為原子型事務(wù)訪問。鎖被加到所屬對(duì)象實(shí)例級(jí).所以 不加nonatomic對(duì)與多線程是安全的 。?
其實(shí)他們都可以用代碼表示:1.nonatomic 和 atomic@property(nonatomic?) NSObject* test1;
@synthesize test1;上面兩句代碼,表示我們對(duì)test1的訪問,是非多線程安全的。@property(atomic) NSObject* test1;
@synthesize test1;上面兩句代碼,表示我們對(duì)test1的訪問,是多線程安全的。其實(shí)也就是在講該成員變量放到互斥代碼中,例如,下面進(jìn)行加鎖。[_internal lock]; // lock using an object-level lock?
id result = [[value retain] autorelease];?
[_internal unlock];?
return result;
就如上面所說 ,這兩個(gè)屬性,是出于對(duì)多線程條件下 ,對(duì)test1的訪問安全。如果你的程序的成員變量不存在安全問題,用nonatomic?就好,因?yàn)檫@樣不要在訪問是進(jìn)行互斥,效率更高。
2. readonly 、readwrite (注,后續(xù)過程我們都會(huì)加入nonatomic 屬性,因?yàn)樗鞘制毡榈?#xff09;2.1 readonly@property(nonatomic??,readonly) NSObject* test1;
@synthesize test1;上面的兩句代碼,objc編輯器將會(huì)為我們翻譯為:@property(nonatomic??,readonly) NSObject* test1; 等同-(NSObject*)test1;
@synthesize test1;等同-(NSObject*)test1{?return test1;}2.2 readwrite?
@property(nonatomic??,readwrite ) NSObject* test1;
@synthesize test1;上面的兩句代碼,objc編輯器將會(huì)為我們翻譯為:@property(nonatomic??,readwrite ) NSObject* test1; 等同-(NSObject*)test1;
-(void)settest1(NSObject* other);@synthesize test1;等同-(NSObject*)test1{?return test1;}-(void)settest1(NSObject* other);
{?test1 = other;}
成員變量的訪問權(quán)限。所以要抓住他們真正價(jià)值。3. assign@property(nonatomic??,assign) NSObject* test1;@synthesize test1;上面兩句:objc編輯器將會(huì)翻譯如下:@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;
@property(nonatomic??,retain) NSObject* test1;等同-(NSObject*)test1;
-(void)settest1(NSObject* other);
-(NSObject*)test1{?return test1;}-(void)settest1(NSObject* other)?{????if (test1!= other)????{??????????????????[test1release];???????????????????test1= [otherretain];?????}}
5. copy@property(nonatomic??,copy) NSObject* test1;
@synthesize test1;
@property(nonatomic??,copy) NSObject* test1;
-(NSObject*)test1;
-(void)settest1(NSObject* other);
-(NSObject*)test1{?return test1;}-(void)settest1(NSObject* other);
{
????????[test1release];?
????????test1= [othercopy];?
????}
}對(duì)于Copy屬性有一點(diǎn)要主要,被定義有copy屬性的對(duì)象必須要符合NSCopying協(xié)議,并且你還必須實(shí)現(xiàn)了-(id)copyWithZoneNSZone*)zone該方法。
代碼才是王道:都是一些簡(jiǎn)單代碼用例//為了更具有普遍性,我選擇用自定義對(duì)象testObj /
//testObj .h
@interface testObj : NSObject{
????
}
@end
/
//testObj .m-(id)copyWithZoneNSZone *)zone
{
????testObj* pObj = [[testObj allocWithZone:zone] init];
????return pObj;
}
@end
///testApp是包含多個(gè)testObj 對(duì)象指針//testApp .h
@interface testApp :
{
????testObj*??test1;
????testObj*??_test2;
}
@property(nonatomic , retain) NSObject* test1;
@property(nonatomic , copy) NSObject* test2;/
//testApp.m@synthesize test1;@synthesize test2 = _test2;//
@synthesize test2 = _test2; //對(duì)這里要特別主要一下,這里可以看作是一種別名機(jī)制,這點(diǎn)和前面類比的C++頭文件和Cpp文件不同。
例如對(duì)于setter函數(shù),objc編輯器將會(huì)按如下方式翻譯如果是@synthesize _test2;setter函數(shù)將是這種形式:-(void)set_test2(NSObject*); //注意中間的下劃線寫成@synthesize test = _test2;setter函數(shù)將是這種形式:
-(void)settest2(NSObject*);// _test2 被 test2替換了
可以看出這種別名機(jī)制,感覺是規(guī)范書寫(其實(shí)更像是規(guī)范Objc的書寫,大家可以看看官方文檔中,成員變量都是前面帶下滑線的(如_test2),所以才搞了這樣一個(gè)別名規(guī)范代碼中的書寫)
//下面是一個(gè)功能函數(shù),-(void )test{test1 = [[testObj alloc]init];// test1??retainCount??=1;
//下面有三種對(duì)test2操作方法:?_test2 = test1; //這里是將test1的指針賦值給_test2指針,注意,并沒有調(diào)用test2的setter方法 ,所以test retainCount??= 1、 test2 retainCount??= 0;?self.test2 = test1;??//這里調(diào)用test2的Copy方法,因此這是test retainCount??= 1、 test2 retainCount??= 1;???test2???= test1; //這段代碼系統(tǒng)將會(huì)提示出錯(cuò)說test2沒有定義。因?yàn)檫@里編譯器認(rèn)為是一條賦值表達(dá)式,將test2看作是一個(gè)成員變量,而在我們的testApp 中是沒有這個(gè)成員變量的,這里要區(qū)別我們所說的別名,別名機(jī)制可以看作是在調(diào)用setter或者getter函數(shù)才會(huì)起作用,而這里只是一個(gè)簡(jiǎn)單的賦值,也就出現(xiàn)未定義的錯(cuò)誤。如果沒有理解,你就記住要調(diào)用setter或者getter函數(shù),就用"self.成員變量"這種形式就行了.
//我們把??test2???= test1這行代碼注釋掉,保證程序繼續(xù)執(zhí)行????[test1 release];??// 釋放test1 ,test1 retainCount??= 0;
????
????[test2 release]; // 釋放test2 ,test2 retainCount??= 0;
}@end
轉(zhuǎn)載于:https://www.cnblogs.com/mafeng/p/5231906.html
總結(jié)
以上是生活随笔為你收集整理的nonatomic, retain,weak,strong用法详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 求一个好听的书屋名字!
- 下一篇: 闷倒驴多少钱一瓶