屬性關(guān)鍵字-(基礎(chǔ)篇)

作為一個開發(fā)者,我們每天都在新的需求中創(chuàng)建一個又一個Object卷雕,每個類都可能會有一些私有或共有的屬性钱雷,來滿足我們的開發(fā)需求骂铁。
那么,每一個屬性要如何來用關(guān)鍵字定義使用罩抗?每個修飾屬性的關(guān)鍵字之間又有什么區(qū)別拉庵,你真的了解嗎?

下面代碼中的修飾屬性的關(guān)鍵字套蒂,大家一定再熟悉不過了钞支,如果你不熟悉,騷年您轉(zhuǎn)行吧!

@interface ViewController ()

@property (nonatomic, assign) NSInteger     persionAge;
@property (nonatomic, copy)   NSString     *persionName;
@property (nonatomic, weak)   UIImageView  *persionIconView;
@property (nonatomic, strong) NSArray      *persionArray;

@end

下面Zombie代大家詳細(xì)了解一下操刀,assign烁挟、copy、weak骨坑、strong之間的同處撼嗓、異處。
是否會開辟新的內(nèi)存
是否會對地址引用計數(shù)增加
哪里講的不好欢唾,歡迎大家留言指出且警、愿意和大家共同探討!

一. 我們舉一個典型的例子非容器可變變量'NSMutableString'來了解一下礁遣。

@interface ViewController ()

@property (nonatomic, copy)   NSString *strCopy;
@property (nonatomic, strong) NSString *strStrong;
@property (nonatomic, weak)   NSString *strWeak;
@property (nonatomic, assign) NSString *strAssign;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSMutableString *testStr = [NSMutableString stringWithString:@"address"];
    self.strCopy= testStr;
    self.strStrong= testStr;
    self.strWeak= testStr;
    self.strAssign= testStr;
    // 輸出結(jié)果
    NSLog(@"testStr   輸出:%p, %@", testStr,  testStr);
    NSLog(@"strCopy   輸出:%p, %@",_strCopy,  _strCopy);
    NSLog(@"strStrong 輸出:%p, %@",_strStrong,_strStrong);
    NSLog(@"strWeak   輸出:%p, %@",_strWeak,  _strWeak);
    NSLog(@"strAssign 輸出:%p, %@",_strAssign,_strAssign);
    
    NSLog(@"引用計數(shù)為%@",[testStr valueForKey:@"retainCount"]);
    // 輸出內(nèi)容
    testStr   輸出:0x60400005d0d0, address
    strCopy   輸出:0xa737365726464617, address
    strStrong 輸出:0x60400005d0d0, address
    strWeak   輸出:0x60400005d0d0, address
    strAssign 輸出:0x60400005d0d0, address
    引用計數(shù)為2
}
以上結(jié)果我們看出
  • strStrong斑芜、strWeakstrAssign指針指向的地址都與testStr相同
  • copy修飾的strCopy祟霍,賦值后則是自己單獨開辟了一塊內(nèi)存地址杏头,內(nèi)存上保存address字符串,并指向它沸呐。
  • testStr的引用計數(shù)為2醇王,并不為4;strWeak垂谢、strAssign指針雖然都指向了testStr的內(nèi)存地址,但并不會使testStr的引用計數(shù)增加厦画。
根據(jù)以上結(jié)果我們可以看出,當(dāng)我們現(xiàn)在修改了testStr的值滥朱,勢必不會對strCopy的值造成影響根暑,OK我們來測試一下。
    [testStr stringByAppendingString:@"_xxoo"];
    NSLog(@"testStr   輸出:%p, %@", testStr,   testStr);
    NSLog(@"strCopy   輸出:%p, %@",_strCopy,   _strCopy);
    NSLog(@"strStrong 輸出:%p, %@",_strStrong, _strStrong);
    NSLog(@"strWeak   輸出:%p, %@",_strWeak,   _strWeak);
    NSLog(@"strAssign 輸出:%p, %@",_strAssign, _strAssign);
    // 輸出內(nèi)容
    testStr   輸出:0x60400005d0d0, address_xxoo
    strCopy   輸出:0xa737365726464617, address      // 未發(fā)生變化
    strStrong 輸出:0x60400005d0d0, address_xxoo
    strWeak   輸出:0x60400005d0d0, address_xxoo
    strAssign 輸出:0x60400005d0d0, address_xxoo
  • 使用copy會重新開辟一塊新的內(nèi)存來保存相同的數(shù)據(jù)徙邻,原內(nèi)存內(nèi)容被修改對它互相不影響排嫌。
  • strong&&weak都指向原來的內(nèi)存地址,所以值也會被修改;
  • strong會使數(shù)據(jù)地址引用計數(shù)+1缰犁,但weak不會淳地。

那么引用計數(shù)+1怖糊,到底有什么實際上的不一樣呢?
我們重新實例化testStr颇象,然后來看下面一段代碼

    testStr = [[NSMutableString alloc] initWithString:@"abc"];
    NSLog(@"引用計數(shù)%@",[testStr valueForKey:@"retainCount"]);
    NSLog(@"testStr   輸出:%p, %@", testStr,   testStr);
    NSLog(@"strCopy   輸出:%p, %@",_strCopy,   _strCopy);
    NSLog(@"strStrong 輸出:%p, %@",_strStrong, _strStrong);
    NSLog(@"strWeak   輸出:%p, %@",_strWeak,   _strWeak);
    NSLog(@"strAssign 輸出:%p, %@",_strAssign, _strAssign);
    // 輸出內(nèi)容
    testStr   輸出:0x608000055c90, abc
    strCopy   輸出:0xa737365726464617, address
    strStrong 輸出:0x60400044df50, address_xxoo
    strWeak   輸出:0x60400044df50, address_xxoo
    strAssign 輸出:0x60400044df50, address_xxoo
  • strCopy我們看出伍伤,并沒有受到任何影響
  • strStrongstrWeak遣钳、strAssign不等于abc,而等于testStr之前的內(nèi)容扰魂,為什么呢?這是因為strStrong使testStr所指向的原地址引用計數(shù)+1蕴茴,所以testStr重新實例化之后并沒有使strWeak劝评、strAssign的值為空。

我們在來看一段代碼倦淀,再來討論蒋畜。

    testStr = [[NSMutableString alloc] initWithString:@"abc"];
    self.strStrong = nil;
    NSLog(@"testStr   輸出:%p, %@", testStr,   testStr);
    NSLog(@"strCopy   輸出:%p, %@",_strCopy,   _strCopy);
    NSLog(@"strStrong 輸出:%p, %@",_strStrong, _strStrong);
    NSLog(@"strWeak   輸出:%p, %@",_strWeak,   _strWeak);
    NSLog(@"strAssign 輸出:%p, %@",_strAssign, _strAssign);
    // 輸出內(nèi)容
    testStr   輸出:0x60c0002464e0, abc
    strCopy   輸出:0xa737365726464617, address
    strStrong 輸出:0x0, (null)
    strWeak   輸出:0x0, (null)
    strAssign···崩潰···
  • 當(dāng)設(shè)置了strStrong為nil后,strStrong指向testStr原來的那一塊內(nèi)存地址引用就會-1撞叽,造成原內(nèi)存地址釋放姻成,所以strWeak為null了,strStrong當(dāng)然也為null能扒。
  • 當(dāng)原內(nèi)存地址釋放后佣渴,指向原內(nèi)存地址的strAssign產(chǎn)生程序崩潰,而strWeak不會初斑。后面我們在講解這是什么原因。
    我們稱會對數(shù)據(jù)地址增加引用計數(shù)的為強(qiáng)引用膨处,不改變引用計數(shù)的為弱引用见秤。

二. 我們來看一下assign&&weak的區(qū)別。
先來看一段代碼

    NSMutableString *testString = [[NSMutableString alloc] initWithString:@"abc"];
    self.strAssign = testString;
    self.strWeak = testString;
    testString = [[NSMutableString alloc] initWithString:@"test"];
    NSLog(@"strWeak   輸出:%p, %@",_strWeak,   _strWeak);
    NSLog(@"strAssign 輸出:%p, %@",_strAssign, _strAssign);
    // 輸出內(nèi)容
    strWeak   輸出:0x0, (null)
    strAssign···崩潰···
  • assign如果賦值為nil的時候真椿,并不會使assign指向的地址的數(shù)據(jù)抹除鹃答,只是對自己的值進(jìn)行釋放。
  • 我們可以發(fā)現(xiàn)在輸出strAssign的時候會出現(xiàn)崩潰的情況突硝。
    原因其實是出現(xiàn)了野指針的問題测摔,strAssignstrWeak相同,指向testString的內(nèi)存地址解恰,但引用計數(shù)不+1锋八。
    當(dāng)testString重新實例化后,原指向的內(nèi)存地址引用計數(shù)為0會被釋放护盈,這個時候assign指向的地址就不存在了挟纱,所以會發(fā)生崩潰;如果這塊內(nèi)存地址沒有被其他內(nèi)容重新占用時腐宋,assign還可以正常輸出內(nèi)容紊服,但是一旦被從新寫入數(shù)據(jù)檀轨,該指針指向地址的內(nèi)容隨時可能沒有值,或錯亂值欺嗤,更及其容易造成崩潰参萄。

三. retain是什么

  • ARC之前屬性構(gòu)造器的關(guān)鍵字是retaincopy煎饼、assign讹挎。
  • strongweak是ARC帶出來的關(guān)鍵字腺占。
  • retain等同于strong淤袜,指針指向值內(nèi)存地址,同時進(jìn)行引用計數(shù)加1衰伯。

四. 非NSMutableString的情況

  • 我在后續(xù) 屬性關(guān)鍵字-(進(jìn)階篇) 和大家一同討論

本章小節(jié)
當(dāng)我們使用strStrong铡羡、strWeakstrAssign意鲸、copy關(guān)鍵字來修飾我們定義的屬性的時候烦周,首先要明確每個關(guān)鍵字的含義,和它們之間的不同點怎顾,再來分配給我們的屬性读慎。
再我們賦值的時候,要想清楚我們的目的槐雾,修改屬性內(nèi)容的時候也要注意修改對其他的對象的值有無其他影響夭委,這樣才能使我們的程序更在穩(wěn)定。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末募强,一起剝皮案震驚了整個濱河市株灸,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌擎值,老刑警劉巖慌烧,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異鸠儿,居然都是意外死亡屹蚊,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進(jìn)店門进每,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汹粤,“玉大人,你說我怎么就攤上這事品追⌒ǎ” “怎么了?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵肉瓦,是天一觀的道長遭京。 經(jīng)常有香客問我胃惜,道長,這世上最難降的妖魔是什么哪雕? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任船殉,我火速辦了婚禮,結(jié)果婚禮上斯嚎,老公的妹妹穿的比我還像新娘利虫。我一直安慰自己,他們只是感情好堡僻,可當(dāng)我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布糠惫。 她就那樣靜靜地躺著,像睡著了一般钉疫。 火紅的嫁衣襯著肌膚如雪硼讽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天牲阁,我揣著相機(jī)與錄音固阁,去河邊找鬼。 笑死城菊,一個胖子當(dāng)著我的面吹牛备燃,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凌唬,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼并齐,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了客税?” 一聲冷哼從身側(cè)響起冀膝,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎霎挟,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體麻掸,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡酥夭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了脊奋。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片熬北。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖诚隙,靈堂內(nèi)的尸體忽然破棺而出讶隐,到底是詐尸還是另有隱情,我是刑警寧澤久又,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布巫延,位于F島的核電站效五,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏炉峰。R本人自食惡果不足惜畏妖,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望疼阔。 院中可真熱鬧戒劫,春花似錦、人聲如沸婆廊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽淘邻。三九已至茵典,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間列荔,已是汗流浹背敬尺。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留贴浙,地道東北人砂吞。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓,卻偏偏與公主長得像崎溃,于是被迫代替她去往敵國和親蜻直。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,691評論 2 361

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