OC:屬性

目錄

  • 屬性演變過程
  • 屬性定義
  • 屬性擴(kuò)展

屬性演變過程

上篇博文《OC學(xué)習(xí)備忘錄:成員變量、方法》中演示了如何聲明成員變量即硼,并在方法中使用鹿响。
這里繼續(xù)以WZKPerson類為例郑现,上篇博文中我們聲明了一個(gè)lisi的對象,并初始化了該對象的name和age兩個(gè)成員變量未荒。

WZKPerson *lisi=[[WZKPerson alloc]initWithName:@"李四" age:30];
[lisi sayMyInfo];

假如我們想給lisi進(jìn)行改名字专挪,該怎么辦呢?
由于成員變量在類的內(nèi)部茄猫,無法直接進(jìn)行修改狈蚤,又該怎么辦呢?
一種簡單的辦法是划纽,可以利用對象方法進(jìn)行修改成員變量脆侮。
首先需要在WZKPerson.h文件中添加如下方法:

-(void)setName:(NSString *)name;
-(void)setAge:(NSInteger)age;

對應(yīng)的需要在.m文件中實(shí)現(xiàn)這兩個(gè)方法:

-(void)setName:(NSString *)name
{
   _name=name;
}
-(void)setAge:(NSInteger)age
{
    _age=age;
}

最后就可以在調(diào)用類中使用這兩個(gè)方法了。

//設(shè)置lisi的name為李斯
[lisi setName:@"李斯"];
//設(shè)置lisi的age為90
[lisi setAge:90];
//輸出設(shè)置name和age信息
[lisi sayMyInfo];

運(yùn)行效果如下:



第二個(gè)運(yùn)行結(jié)果是沒有改變lisi的name和age之前的結(jié)果勇劣,第三個(gè)結(jié)果是改變之后的運(yùn)行結(jié)果靖避。

通過方法修改成員變量的值還是比較簡單的,那么問題又來了比默,現(xiàn)在我們想獲取lisi的name和age值幻捏,又該怎么辦呢?同樣的方式命咐,可以寫一個(gè)新的方法進(jìn)行獲取篡九。

在WZKPerson.h文件中添加如下方法:

-(NSString *)name;
-(NSInteger)age;

對應(yīng)的需要在.m文件中實(shí)現(xiàn)這兩個(gè)方法:

-(NSString *)name
{
    return _name;
}

-(NSInteger)age
{
    return _age;
}

最后就可以在調(diào)用類中使用這兩個(gè)方法了。

NSString *lisiName=[lisi name];
NSInteger lisiAge=[lisi age];
NSLog(@"lisiName= %@ , lisiAge= %li",lisiName,lisiAge);

運(yùn)行效果如下:


這種通過定義方法的方式訪問類的成員變量醋奠,其實(shí)就是利用到了面向?qū)ο笾蟹庋b特性

到現(xiàn)在為止榛臼,通過定義方法的方法的方式設(shè)置和獲取成員變量的值看起來沒有什么問題伊佃,但是會引出一個(gè)問題。
假如又定義了一個(gè)NSMutableString類型的變量personName沛善,將personName值賦值給wangwu的name變量航揉。

NSMutableString *personName=[NSMutableString stringWithString:@"王五"];
[wangwu setName:personName];
NSLog(@"personName= %@,wangwu's name=%@",personName,[wangwu name]);

輸出結(jié)果肯定是:“personName= 王五,wangwu's name=王五”。
現(xiàn)在我希望personName值為“王五123”金刁,wangwu 的name值還是為“王五”帅涂。可能我們會用下面代碼來改變personName的值尤蛮。

[personName appendString:@"123"];

添加完這行代碼后媳友,重新運(yùn)行一下,發(fā)現(xiàn)輸出的結(jié)果為:“personName= 王五123,wangwu's name=王五123”抵屿,和我們預(yù)期的結(jié)果不一樣庆锦,這是什么原因造成呢?
還記得在WZKPerson.m文件中的這兩段代碼嗎轧葛?

-(id)initWithName:(NSString *)name age:(NSInteger)age
{
    self=[super init];
    if (self) {
        _name=name;
        _age=age;
    }
    return  self;
}
-(void)setName:(NSString *)name
{
    _name=name;
}

造成的原因是因?yàn)開name=name導(dǎo)致的搂抒,這又是為什么呢?
這里先來看一下personName和[wangwu name]兩個(gè)值的內(nèi)存地址尿扯。

NSLog(@"%p",personName);
NSLog(@"%p",[wangwu name]);

運(yùn)行后求晶,發(fā)現(xiàn)personName內(nèi)存地址為0x100300aa0,另外[wangwu name]也是0x100300aa0衷笋,這兩個(gè)內(nèi)存地址一樣芳杏,說明通過_name=name賦值方式,[wangwu name]的內(nèi)存地址指向了personName的內(nèi)存地址辟宗,這種方式叫做淺拷貝爵赵。

終于找到原因了,那有沒有解決辦法來實(shí)現(xiàn)我們的預(yù)期結(jié)果呢泊脐?
當(dāng)前可以了空幻,既然有淺拷貝,那必然會有一個(gè)叫深拷貝(copy)的東東容客。那么怎么使用copy呢秕铛?很簡單,直接看代碼缩挑。

-(id)initWithName:(NSString *)name age:(NSInteger)age
{
    self=[super init];
    if (self) {
        _name=[name copy];
        _age=age;
    }
    return  self;
}
-(void)setName:(NSString *)name
{
    _name=[name copy];
}

只需要將原來的_name=name代碼改成_name=[name copy]就可以了但两。
重新運(yùn)行一下,發(fā)現(xiàn)輸出的結(jié)果變?yōu)椋骸皃ersonName= 王五123,wangwu's name=王五”供置,達(dá)到了預(yù)期結(jié)果谨湘。
再來看一下內(nèi)存地址,驗(yàn)證一下是不是指向兩個(gè)不同的內(nèi)存地址。
發(fā)現(xiàn)personName內(nèi)存地址變成了0x1003004d0悲关,而[wangwu name]內(nèi)存地址變成了0x100300a90谎僻。
內(nèi)存地址也不一樣,完全達(dá)到了預(yù)期結(jié)果寓辱。

age成員變量由于是NSInteger類型,不會涉及深拷貝和淺拷貝

但是問題又來了赤拒,我們發(fā)現(xiàn)秫筏,僅僅兩個(gè)簡單成員變量的設(shè)置和獲取操作,就需要寫十幾行的代碼挎挖,如果一個(gè)類里面有十幾個(gè)變量这敬,那么僅僅這一塊代碼就需要上百行,嚴(yán)重影響了開發(fā)效率蕉朵,并且錯(cuò)誤率也會大大的提升崔涂。

屬性定義

蘋果公司在Objective-C 2.0中引入了屬性(property),它組合了新的預(yù)編譯指令和新的屬性訪問器語法始衅。新的屬性功能顯著的減少了冗余代碼的數(shù)量冷蚂。

怎么在上述代碼中添加WZKPerson的name和age的屬性的呢?

首先我們先將WZKPerson類.h和.m文件中:
-setName:汛闸、-setAge:蝙茶、-name:和-age:方法的聲明和實(shí)現(xiàn)注釋掉。

在WZKPerson.h文件添加如下代碼诸老。

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;

最后運(yùn)行一下程序隆夯,發(fā)現(xiàn)輸出的結(jié)果和之前是一樣的。


另外也可以通過點(diǎn)方式設(shè)置或者獲取屬性值别伏。

wangwu.name=@"12345";//等價(jià)于[wangwu setName:@"12345"];
wangwu.age=20;//等價(jià)于[wangwu setAge:20];
[wangwu sayMyInfo];

到此為止蹄衷,我們就成功的添加了WZKPerson類的name和age的屬性,是不是很簡單厘肮。

下面稍微解釋屬性聲明的代碼:

  • OC中可以通過@property聲明屬性愧口;
  • 通過@synthesize自動生成getter、setter方法(目前可以省略@synthesize聲明)轴脐;

屬性聲明后调卑,甚至也可以直接省略掉成員變量的聲明

下面總結(jié)一下屬性的生成規(guī)則:

  1. 如果只聲明了一個(gè)屬性a,不使用@synthesize實(shí)現(xiàn)大咱,編譯器會使用_a作為屬性的成員變量恬涧。
    如果沒有定義成員變量_a,則會自動生成一個(gè)私有的成員變量_a碴巾;
    如果已經(jīng)定義了成員變量_a則使用自定義的成員變量_a溯捆;
    注意,如果此時(shí)定義的成員變量不是_a而是a,則此時(shí)會自動生成一個(gè)成員變量_a提揍,它和自定義成員變量a沒有任何關(guān)系啤月;
  2. 如果聲明了一個(gè)屬性a,使用@synthesize a進(jìn)行實(shí)現(xiàn)劳跃,但是實(shí)現(xiàn)過程中沒有指定使用的成員變量谎仲,則此時(shí)編譯器會使用a作為屬性的成員變量。
    如果定義了成員變量a刨仑,則使用自定義成員變量郑诺;
    如果此時(shí)沒有定義,則自動生成一個(gè)私有的成員變量a杉武;
    注意辙诞,如果此時(shí)定義的是_a,則它跟生成的a成員變量沒有任何關(guān)系轻抱;
  3. 如果聲明了一個(gè)屬性a飞涂,使用@synthesize a=_a進(jìn)行實(shí)現(xiàn),這個(gè)過程已經(jīng)指定了使用的成員變量祈搜,此時(shí)會使用指定的成員變量作為屬性變量较店;

屬性擴(kuò)展

可能大家會發(fā)現(xiàn),在上面聲明屬性代碼中有一個(gè)()號夭问,并且其中有一些參數(shù)泽西。

@property(nonatomic,copy)NSString *name;
@property(nonatomic,assign)NSInteger age;

()號中的參數(shù),我們叫做屬性限定詞缰趋。
這些限定詞包括:nonatomic捧杉、atomic、copy秘血、retain味抖、strong、weak灰粮、assign仔涩、 readonly、readwrite粘舟;
下面簡單的介紹這些限定詞的含義:

限定詞 說明
atomic 默認(rèn)值熔脂,表示原子,同一時(shí)間可以由多個(gè)線程訪問屬性
nonatomic 表示非原子柑肴,同一時(shí)間只能有一個(gè)線程進(jìn)行訪問
readonly 只讀屬性霞揉,只生成getter方法
readwrite 默認(rèn)值,生成getter晰骑、setter方法
assign 默認(rèn)值适秩,直接賦值,通常修飾基本數(shù)據(jù)類型,也可以修飾對象數(shù)據(jù)類型秽荞,但此時(shí)會指向同一個(gè)內(nèi)存地址
retain 先release原來的值骤公,再retain新值,會導(dǎo)致引用計(jì)數(shù)+1
copy 先release原來的值扬跋,再copy新值(深拷貝)
strong iOS4.0之后出來的關(guān)鍵字阶捆,會導(dǎo)致引用計(jì)數(shù)+1,作用等價(jià)于retain
weak iOS4.0之后出來的關(guān)鍵字钦听,用于對象數(shù)據(jù)類型心赶,作用等價(jià)于assign

@property的參數(shù)最多可以有三個(gè)揭蜒,中間用逗號分割。如果不進(jìn)行設(shè)置沉删,程序會使用默認(rèn)參數(shù):(atomic,readwrite,assign)

一般情況下娱挨,如果在多線程開發(fā)中一個(gè)屬性可能會被多個(gè)線程同時(shí)訪問余指,可以考慮用atomic,否則建議使用nonatomic跷坝,效率更高酵镜;

小技巧:通常情況下,字符串對象使用copy柴钻,非字符串對象使用retain淮韭,基本數(shù)據(jù)對象使用assign;
另外使用copy功能需要一些前提贴届,需要遵守NSCopying協(xié)議靠粪,實(shí)現(xiàn)copyWithZone:方法;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末毫蚓,一起剝皮案震驚了整個(gè)濱河市占键,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌元潘,老刑警劉巖畔乙,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異翩概,居然都是意外死亡牲距,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進(jìn)店門钥庇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來牍鞠,“玉大人,你說我怎么就攤上這事上沐∑し” “怎么了?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長龄广。 經(jīng)常有香客問我硫眯,道長,這世上最難降的妖魔是什么择同? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任两入,我火速辦了婚禮,結(jié)果婚禮上敲才,老公的妹妹穿的比我還像新娘裹纳。我一直安慰自己,他們只是感情好紧武,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布剃氧。 她就那樣靜靜地躺著,像睡著了一般阻星。 火紅的嫁衣襯著肌膚如雪朋鞍。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天妥箕,我揣著相機(jī)與錄音滥酥,去河邊找鬼。 笑死畦幢,一個(gè)胖子當(dāng)著我的面吹牛坎吻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宇葱,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼瘦真,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了贝搁?” 一聲冷哼從身側(cè)響起吗氏,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎雷逆,沒想到半個(gè)月后弦讽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡膀哲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年往产,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片某宪。...
    茶點(diǎn)故事閱讀 40,096評論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡仿村,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出兴喂,到底是詐尸還是另有隱情蔼囊,我是刑警寧澤焚志,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站畏鼓,受9級特大地震影響酱酬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜云矫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一膳沽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧让禀,春花似錦挑社、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腮敌,卻和暖如春录平,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缀皱。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留动猬,地道東北人啤斗。 一個(gè)月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓,卻偏偏與公主長得像赁咙,于是被迫代替她去往敵國和親钮莲。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評論 2 355

推薦閱讀更多精彩內(nèi)容

  • @property 功能: 給現(xiàn)有的成員變量生成一對setter、getter方法 如果沒有聲明成員變量時(shí)自動生成...
    李琪_59dc閱讀 4,532評論 0 4
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法凤覆,類相關(guān)的語法链瓦,內(nèi)部類的語法,繼承相關(guān)的語法盯桦,異常的語法慈俯,線程的語...
    子非魚_t_閱讀 31,639評論 18 399
  • 1. 屬性 屬性是 objective-c2.0 定義的語法, 為實(shí)例變量提供了setter和getter方法的默...
    李小六_閱讀 1,664評論 1 4
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn)拥峦,斷路器贴膘,智...
    卡卡羅2017閱讀 134,661評論 18 139
  • OC屬性 [toc] 屬性的作用 1. 為成員變量提供訪問的接口。setter和 getter 方法 @prope...
    One1丨光閱讀 1,423評論 0 4