OC屬性
[toc]
屬性的作用
1. 為成員變量提供訪問的接口。setter和 getter 方法
@property 與 @synthsize 搭配使用,當(dāng)你沒有實(shí)現(xiàn)屬性的setter和 getter方法時(shí),系統(tǒng)會(huì)默認(rèn)幫助生成Setter getter。
-
@synthSize var = _var;
如果沒有生成set、get方法,則默認(rèn)幫助生成訪問器方法。在iOS4.4以前需要搭配@property使用,4.4以后@property不需要顯示聲明@synthsize即可生成訪問器方法。
-
@dynamic var;
聲明dynamic以后將由程序員自己生成set/get方法,并且如果沒有實(shí)現(xiàn)不會(huì)觸發(fā)警告,如果真沒有實(shí)現(xiàn)而又調(diào)用了該屬性,則會(huì)導(dǎo)致crash
2. 屬性修飾符
-
nonatomic/atomic
- nonatomic
- 線程不安全 多個(gè)線程可以同時(shí)對其進(jìn)行訪問,沒有資源保護(hù)
- 訪問速度快
- atomic
- 線程安全 在多線程中只能有一個(gè)線程對進(jìn)行訪問,會(huì)默認(rèn)會(huì)setter方法加鎖(MRC環(huán)境重寫Setter方法需要設(shè)置訪問鎖)
- 訪問效率慢
- nonatomic
-
assign/weak
- assign
- 修飾基本數(shù)據(jù)類型(非指針型變量)setter方法里不會(huì)進(jìn)行任何retain操作
- assign如果拿來修飾對象類型會(huì)有野指針(懸垂指針)的危險(xiǎn)。(MRC使用unsafe_unretained修飾對象類型).assign修飾對象的話,如果對象釋放了不會(huì)置為nil|
- weak
- 修飾對象類型。Arc下使用 和assign的效果一致
- weak比assign優(yōu)化的一點(diǎn)是,當(dāng)對象釋放了以后可以將修飾的指針置為nil,可以有效避免野指針的行為
- assign
copy / Strong / Retain
討論copy 需要補(bǔ)充一下 深拷貝|淺拷貝 的知識
// 結(jié)論
// 1.容器類型的指針 copy 只會(huì)產(chǎn)生不可變對象, mutableCopy 只會(huì)產(chǎn)生可變對象 與指針本身可變性無關(guān)
// 2.容器類型的指針 copy/mutableCopy 只是對數(shù)組內(nèi)部元素指針的復(fù)制,不會(huì)去調(diào)用元素的copy方法,所以copy后新容器內(nèi)部的元素內(nèi)容是不變的。
- copy
// 系統(tǒng)引用計(jì)數(shù)的默認(rèn)實(shí)現(xiàn)
- (void)setName:(NSString *)newname {
if (_name != newname) {
[_name release];
_name = [newname copy];
}
}
由上可以看出:
1. copy 修飾符 會(huì)先對舊對象release,然后copy一份新對象。因此會(huì)對引用計(jì)數(shù)進(jìn)行+1
2. copy 修飾符的特點(diǎn)就是會(huì)對對象進(jìn)行一次copy。
- strong
// 系統(tǒng)引用計(jì)數(shù)的默認(rèn)實(shí)現(xiàn)
- (void)setName:(NSString *)newname {
if (_name != newname) {
[_name release];
_name = [newname retain];
}
}
由上可以看出: **strong 修飾符 會(huì)先對舊對象release,然后賦值并對新對象reatin。也會(huì)對引用計(jì)數(shù)進(jìn)行+1**
- retain
retain 是MRC時(shí)代的產(chǎn)物,retain的實(shí)現(xiàn)和strong是一樣的,因此strong 也可以用于MRC下。
特別注意:對于NSArray,NSDictionary,NSString這樣的不可變對象我們需要使用copy來修飾,如果使用了strong,則對象被賦值了一個(gè)可變對象的時(shí)候,不可變對象的內(nèi)容就可以發(fā)生改變了.容易造成語義的矛盾,也極有影響代碼的運(yùn)行。
-
readonly/readwrite
readwrite就是可讀寫,不加這個(gè)屬性修飾符默認(rèn)就是如此,所有變量都是可以讀寫的,也就是都自帶setter和getter方法,而使用readonly修飾系統(tǒng)會(huì)自動(dòng)生成getter方法而不生成setter方法所以是只讀的,無法賦值。
3.另外一些標(biāo)示符
-
const
NSString const *str = @"123"; NSString * const str1 = @"123"; str = @"456"; // 這句話只是把456的內(nèi)存地址分配給str str 本身是一個(gè)變量,但它指向的內(nèi)存是不可變的 str1 本身是一個(gè)常量,*str1 是一個(gè)變量const 相比 宏定義define:
1. const 在編譯階段參與編譯,宏則是在預(yù)編譯階段 2. 宏不做類型檢查,只是替換內(nèi)容,const 會(huì)編譯檢查類型 3. 宏可以定義函數(shù)方法代碼塊,const不行 -
static
static 修飾的變量都是在字符常量區(qū)- static 修飾全部變量
- 限制了全局變量的作用域?yàn)楫?dāng)前文件內(nèi)
- static 修飾局部變量
- 讓局部變量只初始化一次
- 局部變量在程序中只有一份內(nèi)存
- 并不會(huì)改變局部變量的作用域,僅僅是改變了局部變量的生命周期
- static 修飾全部變量
-
extern
對extern來說,可以理解為擴(kuò)展吧,將當(dāng)前變量的作用域從一個(gè)類擴(kuò)展到另一個(gè)類。