昨天立了flag锅棕,今天就來開始第一篇文章吧。
property的關(guān)鍵字是我們平常寫代碼隨時都會用到的荆烈,只要聲明一個屬性拯勉,就會用到這些關(guān)鍵字竟趾,先從最簡單的講起吧。
一宫峦、如何使用
property的關(guān)鍵字分三類:
- 一類是表示原子性(也就是線程安全)的岔帽,有atomic和nonatomic,默認是atomic导绷,acomic也就是線程安全犀勒,但是我們一般都用的nonatomic,因為atomic的線程安全開銷太大妥曲,影響性能贾费,即使需要保證線程安全,我們也可以通過自己的代碼控制檐盟,而不用atomic褂萧。
- 一類是表示引用計數(shù)的,有assign(iOS5以前用unsafe_unretained),strong,weak,copy葵萎。
assign: assign用于非指針變量导犹,一般用于基礎(chǔ)類型和C數(shù)據(jù)類型,這些類型不是對象羡忘,統(tǒng)一由系統(tǒng)棧進行內(nèi)存管理谎痢。
weak:對對象的弱引用,不增加對象的引用計數(shù)壳坪,也不持有對象舶得,當對象消失后指針自動指向nil,所以這里也就防止了野指針的存在爽蝴。
strong:對對象的強引用沐批,會增加對象的引用計數(shù),如果指向了一個空對象蝎亚,會造成野指針九孩,平常我們用得最多的應(yīng)該也是strong了。
copy:建立一個引用計數(shù)為1的新對象发框,賦值時對傳入值進行一份拷貝躺彬,所以使用copy關(guān)鍵字的時候,你將一個對象復(fù)制給該屬性梅惯,該屬性并不會持有那個對象宪拥,而是會創(chuàng)建一個新對象,并將那個對象的值拷貝給它铣减。而使用copy關(guān)鍵字的對象必須要實現(xiàn)NSCopying協(xié)議她君。
unsafe_unretained:跟 weak 類似,聲明一個弱引用葫哗,但是當引用計數(shù)為 0 時缔刹,變量不會自動設(shè)置為 nil球涛,現(xiàn)在基本都用weak了。 - 一類是表示讀寫權(quán)限的校镐,默認是readwrite(可讀可寫)亿扁,還有就是readonly,當你希望暴露出來的屬性不能被外界修改時就需要申明為readonly鸟廓。
二从祝、關(guān)鍵字與內(nèi)存管理
這里重點講一下與內(nèi)存管理相關(guān)的這幾個關(guān)鍵字。
直接上代碼吧
測試
@property (nonatomic,strong) Person *strongPerson;
@property (nonatomic,weak) Person *weakPerson;
試驗代碼
self.strongPerson = [Person new];
self.weakPerson = self.strongPerson;
self.strongPerson = nil; NSLog(@"strongStr=%@,weakStr=%@",self.strongPerson,self.weakPerson);
輸出結(jié)果為:
strongStr=(null),weakStr=(null)
這里就足以說明weak修飾的屬性并不會使引用計數(shù)增加
稍微修改代碼肝箱,把weakPerson設(shè)置為nil
self.strongPerson = [Person new];
self.weakPerson = self.strongPerson;
self.weakPerson = nil;
NSLog(@"strongStr=%@,weakStr=%@",self.strongPerson,self.weakPerson);
輸出結(jié)果如下:
strongStr=<Person: 0x600000007d50>,weakStr=(null)
說明weak修飾的屬性只是對對象的弱引用哄褒,并不會真正的持有該對象。
再次修改代碼
Person *p = [Person new];
self.strongPerson = p;
self.weakPerson = self.strongPerson;
p = nil;
NSLog(@"strongStr=%@,weakStr=%@",self.strongPerson,self.weakPerson);
輸出結(jié)果為:
strongStr=<Person: 0x600000200b50>,weakStr=<Person: 0x600000200b50>
這里不用多說煌张,因為strong屬性會強引用該對象并使該對象的引用計數(shù)+1,所以即使把p設(shè)置為nil退客,該對象也并沒有釋放骏融,要想釋放該對象,還得把strongStr設(shè)置為nil萌狂。
self.strongPerson = nil;
這樣輸出結(jié)果就是 strongStr=(null),weakStr=(null)
了档玻。
再來看看copy關(guān)鍵字
為了方便試驗,我們直接在ViewController里面加個屬性茫藏。
@property (nonatomic, copy) NSObject *c;
NSObject *a = [[NSObject alloc]init];
self.c = a;
a = nil;
NSLog(@"%@",self.c);
毫無疑問误趴,輸出結(jié)果不為nil。
<NSObject: 0x600000010d90>
在這里要重點說一下务傲,使用NSMutableArray,NSMutableDictionary等可變集合對象的時候千萬不要用copy凉当,這里用copy 99%會出錯,因為當你給該屬性賦值時它會自動調(diào)用對象的copy方法售葡,從而將可變集合轉(zhuǎn)換成不可變集合看杭,把一個不可變集合賦值給一個可變集合,就會造成錯誤挟伙。
感覺寫得有些啰嗦楼雹,我覺得主要是給新人看吧,畢竟我自己當初一直對這些關(guān)鍵字也是懵懵懂懂的尖阔,如果看了我這篇文章還是不能理解贮缅,那應(yīng)該是完全不了解內(nèi)存管理方面的知識,MRC介却、ARC應(yīng)該去了解一下谴供,如果后面有需要,我可能會寫一篇相關(guān)的文章筷笨。
另外憔鬼,還請大神門多多指教龟劲。。轴或。昌跌。
更新
之前是用NSString來做的實驗,但是由于字符串的特殊性照雁,所以有點容易誤導(dǎo)大家蚕愤,現(xiàn)在已經(jīng)全部改成了普通類了。關(guān)于字符串類型饺蚊,主要是蘋果在編譯期做了一些優(yōu)化萍诱,讓它的特性跟普通變量有點類似,在這里就不說太多了污呼,以免給大家造成困惑裕坊。