深入淺出Objective-C筆記(十一)

屬性 (Property)


不使用屬性的情況
@interface People : NSObject
{
    NSString *firstName;
    NSString *lastName;
    double height;
    double weight;
    NSUInteger age;
    NSString *company;
    NSString *title;
    NSString *address;
    NSString *phone;
}

//類里定義了一些數(shù)據(jù)對(duì)應(yīng)的變量卒稳,既然類里有變量骆姐,想使用這個(gè)類码邻,就得定義這些變量相應(yīng)的讀取和設(shè)置的方法。

//對(duì)于類里某個(gè)變量的讀取和修改的方法稱作「訪問器」或「存取器」

- (void)setFirstName:(NSString*)name;
- (NSString)firstName;

- (void)setLastName:(NSString*)name;
- (NSString*)lastName;

- (void)setHeight:(double)h;
- (double)height;

…

@end 

//這個(gè)類里有這么多變量何之,每個(gè)變量都需要聲明設(shè)置和讀取這么兩個(gè)方法躺彬。

//下面是方法的實(shí)現(xiàn)

@implementation People 
- (void)setFirstName:(NSString)name {
    firstName = name;
}

- (NSString*)firstName {
    return firstName;
}

- (void)setLastName:(NSString)name {
    lastName = name;
}

- (NSString*)lastName {
    return lastName;
}

…

@end

//太多重復(fù)代碼了!

使用屬性的情況
@interface People : NSObject

@property NSString *firstName;
@property NSString *lastName;

@property double height;
@property double weight;
@property NSUInteger age;
@property NSString *company;
@property NSString * title;
@property NSString *address;
@property NSString *phone;

@end

@implementation People

@end 

?

  • 在使用property這個(gè)關(guān)鍵字聲明一條屬性的時(shí)候痢甘,OC為我們做的事如下:

property NSString *firstName; OC實(shí)際為我們完成的工作

  NSString *_firstName;

  - (void)setFirstName:(NSString *)firstName;

  - (NSString *)firstName;

  - (void)setFirstName:(NSString *)firstName {
      …
  }

  - (NSString *)firstName {
      …
  }

  //property為每個(gè)變量自動(dòng)定義了設(shè)置和讀取的方法
  • 如何使用屬性?

|操作類型| 使用點(diǎn)號(hào)|使用方法 |
|---|---|
|設(shè)置|people.firstName = @"First Name";|[people setFirstName:@"First Name"];
|讀取|NSString *firstName = people.firstName;|NSString *firstName = [people firstName];


屬性的聲明部分
@property (getter = getName, setter = setName:, readwrite, readonly, atomic, nonatomic, copy) NSString *name;

//包含三部分茉贡,屬性特質(zhì)产阱,屬性類型,屬性名稱
  • 屬性的特質(zhì)

getter 和 setter

getter = getName
setter = setName:
  //getter 和 setter 是為了方便我們自己給設(shè)置和訪問方法起名字
  //這個(gè)例子里块仆,getName  和 setName本來就是默認(rèn)构蹬,但是我們可以換成我們自己想要的

readwrite 和 readonly

@interface People : NSObject

@property NSString *firstName;
@property NSString *lastName;

@property (readonly) NSString *fullName;

@end 
//屬性fullName的特質(zhì)是readonly的王暗,就只可讀,不可修改    

//fullName不是一個(gè)真正的變量庄敛,它是根據(jù)firstName和lastName拼接而成

//所以我們自己去定義這個(gè)屬性的讀取方法

- (NSString *)fullName {
    return [NSString stringWithFormat:@"%@ %@", self.firstName, self.lastName];
}

atomic 和 nonatomic

//因?yàn)橛袝r(shí)要處理多線程并發(fā)的問題俗壹。OC默認(rèn)的屬性特制是atomic,
//當(dāng)我們?cè)诙鄠€(gè)線程同時(shí)訪問一個(gè)屬性的情況下藻烤,
//至少能保證我們這個(gè)屬性讀取到的是完整的绷雏。

//保證線程安全是需要性能開銷的,
//而我們的程序需要處理多線程的情況并不多怖亭,
//很多時(shí)候我們并不需要這個(gè)線程安全特性涎显。
//所以可以使用nonatomic這個(gè)特質(zhì),
//告訴OC我們這個(gè)屬性它不需要處理多線程并發(fā)的問題兴猩,
// 不要額外的增加線程安全的保證了期吓,
//這樣可以提高我們屬性的讀取和寫入的效率。

@property (readonly, nonatomic) NSString *fullName;

一些跟內(nèi)存管理相關(guān)的特制:strong, weak, copy

strong

//OC在定義對(duì)象類型屬性的時(shí)候默認(rèn)的特質(zhì)就是strong
//當(dāng)我們把一個(gè)對(duì)象B賦值給對(duì)象A的的屬性之后倾芝,對(duì)象A就持有B讨勤,
//B的引用計(jì)數(shù)就會(huì)加一,對(duì)象A還在晨另,對(duì)象B就不會(huì)被銷毀和釋放
//使用strong會(huì)出現(xiàn)一種叫循環(huán)引用的問題

@interface Person : NSObject

@end


@interface Car : NSObject
@property (nonatomic, strong) Person *driver;
@end 

//只要Car對(duì)象沒被銷毀潭千, Person對(duì)象也不會(huì)被銷毀

//但如果司機(jī)也想知道當(dāng)前駕駛的車是哪一輛,
//這個(gè)時(shí)候給司機(jī)增加一個(gè)汽車屬性借尿,代碼如下:

@class Car;
@interface Person : NSObject
@property (nonatomic, strong) Car *car;
@end

@interface Car : NSObject
@property (nonatomic, strong) Person *driver;
@end 

//這時(shí)司機(jī)和汽車相互引用刨晴,且他們的屬性都有strong特質(zhì),
//它們會(huì)使得對(duì)方引用計(jì)數(shù)都加一
//如果沒有任何變量指向這兩個(gè)對(duì)象時(shí)路翻,表示它們已經(jīng)沒用了狈癞,它們本應(yīng)該被銷毀,
//可是這倆對(duì)象卻不會(huì)被銷毀帚桩,因?yàn)樗麄兓ハ嘁弥诩荩糜?jì)數(shù)都還為1.
//它們永遠(yuǎn)不會(huì)被釋放,永遠(yuǎn)占著內(nèi)存
//這就是內(nèi)存泄露問題
//所以O(shè)C增加了一個(gè)屬性特質(zhì):weak

weak

//如果一個(gè)屬性被說明成weak账嚎,那當(dāng)它引用其他對(duì)象的時(shí)候莫瞬,它不會(huì)增加對(duì)方的引用計(jì)數(shù)
//如果這個(gè)對(duì)象被銷毀了,這個(gè)屬性的值就會(huì)自動(dòng)變成nil郭蕉,就避免了C語言里的懸掛指針問題
//因?yàn)槭褂脀eak沒有增加對(duì)方的引用計(jì)數(shù)疼邀,所以就不會(huì)造成循環(huán)引用問題

@class Car;//類的前置聲明,因?yàn)樵诙xPerson類的時(shí)候召锈,使用了Car類旁振,此時(shí)Car類未被聲明,所以需要這個(gè)前置聲明
@interface Person : NSObject
@property (nonatomic, weak) Car *car;
@end

@interface Car : NSObject
@property (nonatomic, strong) Person *driver;
@end 

copy

//對(duì)于一個(gè)對(duì)象類型的屬性來說,當(dāng)我們給這個(gè)屬性賦值的時(shí)候拐袜,實(shí)際存儲(chǔ)的是這個(gè)對(duì)象的引用
//也就會(huì)存在一種可能吉嚣,當(dāng)我們給屬性賦值之后,我們還可以在外部去修改這個(gè)對(duì)象的值蹬铺,
//從而影響到屬性的值

@interface People : NSObject

@property (nonatomic, strong) NSString *name;//People類有一個(gè)NSString類型的屬性name

@end

People *p = [[People alloc] init];

NSMutableString *name = [NSMutableString stringWithString:@"Hello"];

p.name = name;//在對(duì)象p完全不知情的情況下尝哆,name屬性被改了,之前name屬性是被賦值為Hello甜攀。

NSLog(@"name: %@", p.name);

[name appendString:@"World!"];

NSLog(@"name: %@", p.name);

//把name屬性的strong特質(zhì)改為copy特質(zhì)秋泄,再操作 p.name =  name 這句的時(shí)候,實(shí)際上是給一個(gè)復(fù)制出來的新對(duì)象進(jìn)行賦值规阀,并不會(huì)影響之前的屬性賦值

屬性的實(shí)現(xiàn)部分

如果我們聲明了一條屬性恒序,OC會(huì)幫我們自動(dòng)定義對(duì)應(yīng)的變量。默認(rèn)情況下:

//@property NSString *firstName;的實(shí)現(xiàn)

NSString *_firstName;

- (void)setFirstName:(NSString *)firstName;

- (NSString *)firstName;

- (void)setFirstName:(NSString *)firstName {
    …
}

- (NSString *)firstName {
    …
}

//_firstName是OC自動(dòng)幫我們生成的谁撼,如果我想用自己定義的變量名歧胁,
//則可以在類的實(shí)現(xiàn)部分使用@synthesize關(guān)鍵字

@interface People : NSObject

@property (nonatomic, strong) NSString *firstName;

@end

@implementation People

@synthesize firstName = _fname;

@end

//這樣屬性為firstName生成的變量名就變成了_fname

小結(jié)

屬性聲明的語法
屬性的特質(zhì)

小結(jié)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市彤敛,隨后出現(xiàn)的幾起案子与帆,更是在濱河造成了極大的恐慌了赌,老刑警劉巖墨榄,帶你破解...
    沈念sama閱讀 219,427評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異勿她,居然都是意外死亡袄秩,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,551評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門逢并,熙熙樓的掌柜王于貴愁眉苦臉地迎上來之剧,“玉大人,你說我怎么就攤上這事砍聊”臣冢” “怎么了?”我有些...
    開封第一講書人閱讀 165,747評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵玻蝌,是天一觀的道長蟹肘。 經(jīng)常有香客問我,道長俯树,這世上最難降的妖魔是什么帘腹? 我笑而不...
    開封第一講書人閱讀 58,939評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮许饿,結(jié)果婚禮上阳欲,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好球化,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,955評(píng)論 6 392
  • 文/花漫 我一把揭開白布秽晚。 她就那樣靜靜地躺著,像睡著了一般筒愚。 火紅的嫁衣襯著肌膚如雪爆惧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,737評(píng)論 1 305
  • 那天锨能,我揣著相機(jī)與錄音扯再,去河邊找鬼。 笑死址遇,一個(gè)胖子當(dāng)著我的面吹牛熄阻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播倔约,決...
    沈念sama閱讀 40,448評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼秃殉,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了浸剩?” 一聲冷哼從身側(cè)響起钾军,我...
    開封第一講書人閱讀 39,352評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎绢要,沒想到半個(gè)月后吏恭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,834評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡重罪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,992評(píng)論 3 338
  • 正文 我和宋清朗相戀三年樱哼,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片剿配。...
    茶點(diǎn)故事閱讀 40,133評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搅幅,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呼胚,到底是詐尸還是另有隱情茄唐,我是刑警寧澤,帶...
    沈念sama閱讀 35,815評(píng)論 5 346
  • 正文 年R本政府宣布蝇更,位于F島的核電站沪编,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏簿寂。R本人自食惡果不足惜漾抬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,477評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望常遂。 院中可真熱鬧纳令,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,022評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至捏雌,卻和暖如春跃赚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背性湿。 一陣腳步聲響...
    開封第一講書人閱讀 33,147評(píng)論 1 272
  • 我被黑心中介騙來泰國打工纬傲, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人肤频。 一個(gè)月前我還...
    沈念sama閱讀 48,398評(píng)論 3 373
  • 正文 我出身青樓叹括,卻偏偏與公主長得像,于是被迫代替她去往敵國和親宵荒。 傳聞我的和親對(duì)象是個(gè)殘疾皇子汁雷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,077評(píng)論 2 355