1. 成員變量介紹
1. 成員變量解釋
我們把Objective-C中寫在類聲明的大括號(hào)中的變量稱之為成員變量(也稱為屬性蛤育,實(shí)例變量)。
- 舉例:
@interface Iphone : NSObject
{
// 成員變量聲明
int _cpu; // cup 0
int _size; // 尺寸 0
int _color; // 顏色 0
// 其中_cpu、_size敲董、_color 就是 Iphone 類的成員變量
}
2. 成員變量特點(diǎn)
- 成員變量只能通過對(duì)象來訪問
- 成員變量不能離開類,離開類之后就不是成員變量
- 成員變量不能再定義的同時(shí)進(jìn)行初始化
- 成員變量存儲(chǔ)在當(dāng)前對(duì)象對(duì)應(yīng)的堆的存儲(chǔ)空間中慰安,不會(huì)被自動(dòng)釋放腋寨,只能手動(dòng)釋放
- 成員變量前加下劃線"_"是蘋果的編程規(guī)范,或者說是程序員的習(xí)慣化焕。這樣寫的好處在下邊會(huì)提到
2. setter和getter方法
我們無法從外界(比如其他類和文件中)直接訪問定義在類中的成員變量萄窜。為了能夠從外界操作成員變量,我們需要為調(diào)用者提供相應(yīng)的方法來對(duì)成員變量進(jìn)行訪問撒桨、賦值等操作查刻。而定義這些方法都需要有一個(gè)有意義的名字,所以就有了getter-setter方法凤类。
getter-setter方法格式和寫法是固定的穗泵,這也是程序員之間的一種規(guī)范,只要有人想要訪問成員變量或給成員變量賦值谜疤,就會(huì)立刻想到getter-setter方法佃延,這樣就降低了程序員之間的溝通成本。
1. setter方法
- 作用:用來設(shè)置成員變量夷磕,給成員變量賦值苇侵,可以在方法里面對(duì)變量進(jìn)行判斷,過濾掉一些不合理的值
- 命名規(guī)范:
- 必須是對(duì)象方法
- 返回值類型為void
- 方法名必須以set開頭企锌,而且后面跟上成員變量名去掉”_” 榆浓,首字母必須大寫
- 必須提供一個(gè)參數(shù),參數(shù)類型必須與所對(duì)應(yīng)的成員變量的類型一致
- 形參名稱和成員變量去掉下劃線相同
- 舉例:
如:如果成員變量為int _size 那么與之對(duì)應(yīng)seter方法聲明為
-(void) setSize: (int) size;
- setter方法的實(shí)現(xiàn)
- (void)setSize:(int)size;
{
//成員變量以下劃線開頭的好處,就是可以區(qū)分局部變量和成員變量
_size = size;
}
- setter方法的好處
- 不讓數(shù)據(jù)暴露在外,保證了數(shù)據(jù)的安全性
- 對(duì)設(shè)置的數(shù)據(jù)進(jìn)行判斷撕攒,過濾不合理的值(比如空值陡鹃、負(fù)數(shù)等等)
2. getter方法
- 作用:為調(diào)用者返回對(duì)象內(nèi)部的成員變量的值烘浦,用來訪問成員變量
- 命名規(guī)范:
- 必須是對(duì)象方法
- 必須有返回值,返回值的類型和成員變量的類型一致
- 方法名必須是成員變量去掉下劃線
- 一定是沒有參數(shù)的
- 舉例
如:如果成員變量為int _size 那么與之對(duì)應(yīng)getter方法為
- (int) size;
- getter方法的實(shí)現(xiàn)
- (int)size
{
return _size;
}
-
getter方法的優(yōu)點(diǎn):
- 可以讓我們?cè)谑褂胓etter方法獲取數(shù)據(jù)之前,對(duì)數(shù)據(jù)進(jìn)行加工
- 比如雙十一活動(dòng),我們希望對(duì)全線商品的價(jià)格在原來的價(jià)格基礎(chǔ)上打五折萍鲸,那么我們只要去改成品類的價(jià)格的getter方法就可以了闷叉,讓他返回的值為價(jià)格 * 0.5
3. getter/setter方法注意
- 在實(shí)際的開發(fā)中,setter和getter方法不一定都會(huì)提供脊阴。如果內(nèi)部的成員變量握侧,只允許外界讀取,但是不允許修改嘿期,則通常只提供getter方法而不提供setter方法
- 成員變量名的命名以下劃線開頭品擎,setter和getter方法名不需要帶下劃線
- 成員變量名使用下劃線開頭有兩個(gè)好處
- 與getter方法的方法名區(qū)分開來
- 可以和一些其他的局部變量區(qū)分開來,下劃線開頭的變量备徐,通常都是類的成員變量萄传。當(dāng)我看到以下劃線開頭變量,那么他一定是成員變量
3. 點(diǎn)語法
1. 點(diǎn)語法基本使用
如果給成員變量提供了getter和setter方法蜜猾,就可以通過點(diǎn)語法
來訪問成員變量
2. 點(diǎn)語法的本質(zhì)
- 其實(shí)點(diǎn)語法的本質(zhì)就是調(diào)用了setter方法和getter方法
- 當(dāng)使用點(diǎn)語法時(shí)秀菱,編譯器會(huì)在程序翻譯成二進(jìn)制的時(shí)候?qū)?code>.語法自動(dòng)轉(zhuǎn)換為setter和getter方法
- 如果點(diǎn)語法在
=
號(hào)左邊,那么編譯器會(huì)自動(dòng)轉(zhuǎn)換為setter方法 - 如果點(diǎn)語法在
=
號(hào)右邊蹭睡,或者沒有等號(hào)衍菱,那么編譯器就會(huì)自動(dòng)轉(zhuǎn)換為getter方法
3. 點(diǎn)語法注意
- 點(diǎn)語法的本質(zhì)是方法的調(diào)用,而不是訪問成員變量肩豁,當(dāng)使用點(diǎn)語法時(shí)脊串,編譯器會(huì)自動(dòng)展開成相應(yīng)的方法調(diào)用
- 如果沒有setter和getter方法,則不能使用點(diǎn)語法
- 不要在setter與getter方法中使用本屬性的點(diǎn)語法
- (void) setAge:(int)age {
// 下面的代碼會(huì)引發(fā)死循環(huán)
self.age = age;
//編譯器展開后 [self setAge:age]
}
- (int) age {
// 下面的代碼會(huì)引發(fā)死循環(huán)
return self.age;
// 編譯器展開后 [self age]
}
4. 實(shí)例變量修飾符
1. 實(shí)例變量的作用域
- @public
- 公開的
- 在有對(duì)象的前下蓖救,任何地方都可以直接訪問
- @protected
- 受保護(hù)的
- 只能在當(dāng)前類和子類的對(duì)象方法中訪問
- @private
- 私有的
- 只能在當(dāng)前類的對(duì)象方法中才能直接訪問
- @package
- 框架級(jí)別的
- 作用域介于私有和公開之間洪规,只要處于同一個(gè)框架中相當(dāng)于@public,在框架外部相當(dāng)于@private
- 舉例:
@interface Iphone : NSObject
{
@public
int _cpu;
@private
int _size;
@protected
int _color;
@package
double _weight;
}
@end
2. 變量修飾符的繼承和在子類中的訪問
修飾符 | 類別 | 能否繼承 | 在子類中的訪問 |
---|---|---|---|
@private | 私有成員 | 能被繼承 | 不能被外部方法訪問 |
@public | 共有成員 | 能被繼承 | 不能被外部方法訪問 |
@protected | 保護(hù)成員 | 能被繼承 | 不能被外部方法訪問 |
3. 實(shí)例變量作用域使用注意事項(xiàng)
- 在@interface @end之間聲明的成員變量如果不做特別的說明,那么其默認(rèn)是protected的
- 一個(gè)類繼承了另一個(gè)類,那么就擁有了父類的所有成員變量和方法,注意所有的成員變量它都擁有循捺,只是有的它不能直接訪問斩例。例如@private的
5. @property相關(guān)
1. 什么是@property
- @property是是聲明屬性的語法
- @property用在聲明文件中告訴編譯器聲明成員變量的的訪問器(getter/setter)方法
- 使用@property的好處是:免去我們手工書寫getter和setter方法繁瑣的代碼
2. @property基本使用
- 在@inteface中,@property用來自動(dòng)生成setter和getter的聲明
比如用@property int size;就可以代替下面的兩行聲明
- (int)size; // getter
- (void)setSize:(int)size; // setter
- @property編寫步驟
- 在@inteface和@end之間寫上@property
- 在@property后面寫上需要生成getter/setter方法聲明的屬性名稱从橘,注意因?yàn)間etter/setter方法名稱中的屬性不需要
_
念赶,所以@property后的屬性也不需要_
。并且@property和屬性名稱之間要用空格隔開 - 在@property和屬性名字之間告訴需要生成的屬性的數(shù)據(jù)類型, 注意兩邊都需要加上空格隔開
6. @synthesize相關(guān)
1. 什么是@synthesize
- @synthesize是實(shí)現(xiàn)屬性方法的語法
- @synthesize用在實(shí)現(xiàn)文件中告訴編譯器實(shí)現(xiàn)成員變量的的訪問器(getter/setter)方法
- 使用@synthesize好處是:免去我們手工書寫getterr和setter方法繁瑣的代碼
2. @synthesize基本使用
- 寫在@implementation中恰力,用來自動(dòng)生成setter和getter的實(shí)現(xiàn)
用@synthesize size; 就可以代替
- (int)size{
}
- (void)setSize:(int)size{
}
//注意:@synthesize size; 并沒有告訴setter和getter 把size賦值給誰叉谜,返回誰
而用@synthesize size= _size;就可以代替
- (int)size{
return _size;
}
- (void)setSize:(int)size{
_size = size;
}
- @synthesize編寫步驟
- 在@implementation和@end之間寫上@synthesize
- 在@synthesize后面寫上和@property中一樣的屬性名稱,這樣@synthesize就會(huì)將@property生成的什么拷貝到@implementation中
- 由于getter/setter方法實(shí)現(xiàn)是要將傳入的形參給屬性和獲取屬性的值踩萎,所以在@synthesize的屬性后面寫上要將傳入的值賦值給誰和要返回哪個(gè)屬性的值, 并用等號(hào)連接
3. @synthesize注意點(diǎn)
- @synthesize age = _age;
- setter和getter實(shí)現(xiàn)中會(huì)訪問成員變量_age
- 如果成員變量_age不存在停局,就會(huì)自動(dòng)生成一個(gè)@private的成員變量_age
- @synthesize age;
- setter和getter實(shí)現(xiàn)中會(huì)訪問@synthesize后同名成員變量age
- 如果成員變量age不存在,就會(huì)自動(dòng)生成一個(gè)@private的成員變量age
- 多個(gè)屬性可以通過一行@synthesize搞定,多個(gè)屬性之間用逗號(hào)連接
@synthesize age = _age, number = _number, name = _name;
7. @property拓展
1. @property增強(qiáng)
- 自Xcode4.4以后,apple對(duì)@property進(jìn)行了一個(gè)增強(qiáng)董栽,以后不用再寫@synthesize了码倦,只用一個(gè)@property就可以同時(shí)生成setter/getter方法的聲明和實(shí)現(xiàn)
- 如果沒有告訴@property要將傳入的參數(shù)賦值給誰,默認(rèn)@property會(huì)將傳入的屬性賦值給_開頭的成員變量
用@property int size;就可以替代下面兩行聲明
- (int)size; // getter
- (void)setSize:(int)size; // setter
以及下面兩行實(shí)現(xiàn)
- (int)size{
return _size;
}
- (void)setSize:(int)size{
_size = size;
}
- @property只會(huì)生成最簡單的getter和setter方法的聲明和實(shí)現(xiàn)锭碳,并不會(huì)對(duì)傳入的數(shù)據(jù)進(jìn)行判斷
- 如果想對(duì)傳入的數(shù)據(jù)進(jìn)行過濾袁稽,那么我們就必須重寫getter/setter方法
- 如果不想對(duì)傳入的數(shù)據(jù)進(jìn)行過濾,僅僅是提供一個(gè)方法給外界操作成員變量擒抛,那么就可以使用@property
- 如果重寫了setter方法推汽,那么property就只會(huì)生成getter方法
- 如果重寫了getter方法,那么property就只會(huì)生成setter方法
- 如果同時(shí)重寫了getter/setter方法歧沪,那么property就不會(huì)自動(dòng)幫我們生成_開頭的成員變量(報(bào)錯(cuò))
- 如果利用@property來生成getter/setter方法歹撒,那么我們可以不寫成員變量, 系統(tǒng)會(huì)自動(dòng)給我們生成一個(gè)_開頭的成員變量
- 但@property自動(dòng)幫我們生成的成員變量是一個(gè)私有的成員變量, 也就是說是在.m文件中生成的, 而不是在.h文件中生成的。我們?cè)谄渌募袩o法查看該成員變量槽畔,但是可在本類中查看
@property int size;
// 幫我們生成了一個(gè)_size的成員變量栈妆,而該成員變量_size是私有成員變量
2. @property修飾符
- 多線程管理
- atomic 默認(rèn)什么不寫就是atomic胁编,意思是只有一個(gè)線程訪問實(shí)例變量厢钧。效率很低
- nonatomic 可以使用多個(gè)線程訪問實(shí)例變量。效率很快嬉橙,絕大多數(shù)情況下使用nonatomic
- 修飾是否生成getter方法的
- readonly 只生成getter方法早直,不生成setter方法
- readwrite 既生成getter,又生成setter方法(默認(rèn))
@property (nonatomic, readonly) int size;
@property (nonatomic, readwrite) int color;
- 給所生成的getter/setter方法另起一個(gè)名稱
- getter=你定義的getter方法名稱
- setter=你定義的setter方法名稱(注意setter方法必須要有 :)
@property (nonatomic, getter=isMarried) BOOL married;
// 說明市框,通常BOOL類型的屬性的getter方法要以is開頭
-
控制setter方法的內(nèi)存管理
- assign(默認(rèn)):不會(huì)幫我們生成setter方法內(nèi)存管理的代碼霞扬,僅僅只會(huì)生成普通的getter/setter方法,用于直接賦值枫振,不做任何內(nèi)存管理(默認(rèn)喻圃,用于非OC對(duì)象類型)。默認(rèn)什么都不寫就是assign粪滤。被assign修飾的變量不是一個(gè)對(duì)象斧拍。主要用于代表簡單的數(shù)據(jù)類型,比如int杖小、float等肆汹。
@property(nonatomic, assign) int size;
- retain:會(huì)自動(dòng)幫我們生成getter/setter方法內(nèi)存管理的代碼,在setter方法中予权,對(duì)傳入的對(duì)象進(jìn)行引用計(jì)數(shù)加1的操作昂勉。retain一般用于NSObjct類以及其子類
@property (nonatomic, retain) NSNumber *count; // 編譯器為其生成的setter/getter方法 -(NSNumber *)count { // getter方法 return _count; } -(void)setCount:(NSNumber *)count { // setter // 1.判斷傳入的對(duì)象和當(dāng)前對(duì)象是否一樣 if (_count != count) { // 2.release以前的對(duì)象 [_count release]; // 3.retain傳入的對(duì)象 _count = [count retain]; } }
- copy:對(duì)原有對(duì)象進(jìn)行拷貝。常用于NSString類
@property (nonatomic, copy) NSString *string;
- strong:開啟ARC時(shí)才使用扫腺。強(qiáng)引用指針岗照,相當(dāng)于retain。默認(rèn)情況下為strong
@property (nonatomic, strong) UIButton *btn;
- weak:開啟ARC時(shí)才使用。弱引用指針攒至,相當(dāng)于assign
@property (nonatomic, weak) UIButton *btn;