屬性特質(zhì)分為4種
1掀虎、原子性
2、讀寫權(quán)限
3十气、內(nèi)存管理語義
4春霍、方法名
</br>
1砸西、原子性(2種)
(1)atomic(默認(rèn))
(2)nonatomic
2址儒、讀寫權(quán)限(2種)
(1)readwrite(默認(rèn))
(2)readonly
3、內(nèi)存管理語義(5種) ——這組特質(zhì)僅會影響“設(shè)置方法”莲趣,即setter
(1)assgin (非對象類型默認(rèn)屬性,相當(dāng)于unsafe_unretained走芋,適用于int绩郎、float翁逞、CGFloat、NSInteger等)
(2)unsafe_unretained (對象類型默認(rèn)屬性状植,相當(dāng)于assgin怨喘,適用于NSObject津畸、NSArray必怜,NSDictionary等)
(3)weak
(4)strong
(5)copy
4、方法名
(1)編譯器會自動生成屬性存取方法(默認(rèn))
(2)getter = <取值方法名>
(3)setter = <設(shè)置方法名>
比如帝簇,自己寫了一個屬性name
@property (strong, nonatomic) NSString *name;
以下2個方法將自動生成,但不會在編輯器Xcode里面看到:
- (void)setName: (NSString *)name {
...
}
- (NSString *)name {
...
}
如果不想要默認(rèn)的存取方法名丧肴,就可以使用這個特質(zhì)寫一個自定義的方法名:
@property (strong, nonatomic, setter=setMyName) NSString *name;
這樣設(shè)置方法名就會變成下面這樣
- (void)setMyName: (NSString *)name {
...
}
同理胧后,在屬性特質(zhì)中加入 getter = xxx 可自定義取值方法。
我們可以同時把4種特質(zhì)都用上壳快,像下面這樣:
@property (nonatomic, readwrite, strong, getter=myName, setter=setMyName) *name;
</br>
特質(zhì)在確定屬性需求時最好顯式指定,便于自己和他人理解其語義
除以下特殊情況外:讀寫權(quán)限為readwrite時可省略瘤旨。
如果需要一個nonatomic,readwrite存哲,unsafe_unretained七婴,使用默認(rèn)存取方法的name屬性
不推薦的寫法:
@property (nonatomic) NSString *name;
推薦的寫法:
@property (nonatomic, unsafe_unretained) NSString *name;
</br>
每個屬性特質(zhì)適用情景
1、原子性
atomic:
在iOS開發(fā)中幾乎不用打厘,有性能問題;Mac OS X開發(fā)可用嵌施。對象和非對象都能用饲化。
nonatomic:
在iOS開發(fā)中幾乎要用到艰管。對象和非對象都能用。
2、讀寫權(quán)限
readwrite:
屬性擁有g(shù)etter和setter捺球。
readonly:
屬性只有g(shù)etter,讀操作會被視為非法裂逐。
如果要對外公開屬性為只讀,對內(nèi)進(jìn)行讀寫泣栈,可以這么做:
//Person.h
@interface Person: NSObject
@property (nonatomic, readonly, copy) NSString *firstName;
@property (nonatomic, readonly, copy) NSString *lastName;
@end
//Person.m
@interface Person () {
@property (nonatomic, readwrite, copy) NSString *firstName;
@property (nonatomic, readwrite, copy) NSString *lastName;
}
@implementation Person
@end
在實現(xiàn)文件中Person類分類定義了firstName和lastName的讀寫權(quán)限是readwrite南片,所以可以在實現(xiàn)文件內(nèi)部修改它們掺涛。但在外部看來疼进,它們是不可寫的。
3拣帽、內(nèi)存管理語義(“持有”嚼锄、“保留”、“釋放”等概念均源于MRC)
assign:
非對象類型唯一可用內(nèi)存管理語義区丑。你不用就沒得用了。
unsafe_unretained:
非持有關(guān)系(不保留刊苍,"unretained")。意思是啥纸,為這種屬性設(shè)置新值時婴氮,設(shè)置方法既不會保留新值盾致,也不釋放舊值荣暮。當(dāng)目標(biāo)對象被銷毀時,屬性值不會自動清空(不安全穗酥,"unsafe")。
weak:
非持有關(guān)系砾跃。意思是,為這種屬性設(shè)置新值時判耕,設(shè)置方法既不會保留新值翘骂,也不釋放舊值。當(dāng)目標(biāo)對象被銷毀時碳竟,屬性值會自動清空(置為nil)。
strong:
持有關(guān)系方仿。意思是统翩,為這種屬性設(shè)置新值時仙蚜,設(shè)置方法會先保留新值厂汗,再釋放舊值,然后設(shè)置新值贾节。
copy:
用來保護(hù)屬性的封裝性衷畦。使用了copy,等于給設(shè)置方法加了一條copy語句祈争。
沒有使用copy的設(shè)置方法:
- (void)setName: (NSString *)name {
_name = name;
}
使用了copy的設(shè)置方法:
- (void)setName: (NSString *)name {
_name = [name copy];
}
如何保護(hù)?設(shè)置方法會遇到2種情況忿墅,還是用屬性name的例子來說明
第一種情況,設(shè)置方法傳入的是一個不可變字符串:
- (void)setName: (NSString *)name {
_name = [name copy];
}
設(shè)置方法的參數(shù)name是一個NSString類型疚脐。對NSString類型發(fā)送copy消息,是淺復(fù)制望薄,只復(fù)制了指針照卦,_name和參數(shù)name指向同一個地址。這種情況可以說strong與copy無異役耕,它相當(dāng)于執(zhí)行下面這個方法:
- (void)setName: (NSString *)name {
_name = name;
}
第二種情況聪廉,設(shè)置方法傳入的是一個可變字符串:
- (void)setName: (NSString *)name {
_name = [name copy];
}
設(shè)置方法的參數(shù)name是一個NSMutableString類型。因為NSMutableString是NSString的子類板熊,合法。對NSMutableString類型發(fā)送copy消息津辩,是深復(fù)制容劳。_name和參數(shù)name指向不同的地址。這樣你在外部修改了參數(shù)name竭贩,_name也不會變,這就保護(hù)了_name的封裝性窄赋。