OC @Property屬性

[TOC]

本質(zhì)是什么

實(shí)際上@property = 實(shí)例變量 + get方法 + set方法度陆。也就是說(shuō)屬性
@property name: setter方法+getter方法+_name

自動(dòng)合成

定義一個(gè)property岩臣,在編譯期間巨坊,編譯器會(huì)生成實(shí)例變量,getter方法悍募、setter方法茧彤,這些方法是通過(guò)自動(dòng)合成(autosynthesize)的方式生成并添加到類(lèi)中。
實(shí)際上继准,一個(gè)類(lèi)經(jīng)過(guò)編譯后枉证,會(huì)生成變量列表ivar_list,方法列表移必,method_list室谚。每添加一個(gè)屬性,在變量列表ivar_list會(huì)添加對(duì)應(yīng)的變量崔泵,如_name秒赤,在方法列表method_list中會(huì)添加對(duì)應(yīng)的setter和getter方法。

@synthesize name = _name;

手動(dòng)合成

那么有自動(dòng)合成憎瘸,就有手動(dòng)合成入篮。
手動(dòng)合成代碼

@dynamic sex;

這樣就告訴編譯器,sex屬性的實(shí)例變量幌甘,getter方法潮售、setter方法都由開(kāi)發(fā)者自己添加

//下面代碼不添加,在使用該屬性時(shí)候锅风,程序會(huì)崩潰
@interface Student : NSObject
{
    NSString *_sex;
}

@property (nonatomic, copy) NSString *name;

@property (nonatomic, copy) NSString *sex;

@end

整體代碼

@property (nonatomic,copy) NSString *name;///< name
@end

@implementation ViewController
/*
    兩個(gè)一起寫(xiě)會(huì)報(bào)錯(cuò)酥诽,因?yàn)橹貙?xiě)了get和set方法,編譯器認(rèn)為開(kāi)發(fā)者想手動(dòng)管理@property皱埠,此時(shí)會(huì)將@property作為@dynamic來(lái)處理
    因此也就不會(huì)自動(dòng)生成變量肮帐。解決方法,顯示的將屬性和一個(gè)變量綁定:@synthesize name = _name;
    @synthesize name = _name;
*/
@synthesize name = _name;
- (void)setName:(NSString *)name{
    _name = name;
}

//get 不能使用self. 會(huì)造成死循環(huán)
-(NSString *)name{
    return _name;
//    return self.name;  // 錯(cuò)誤的寫(xiě)法边器,會(huì)造成死循環(huán)

}

@property修飾符

  1. 修飾符的種類(lèi)
    1. 原子性 -nonatomic, atomic
    2. 讀寫(xiě)權(quán)限 -readwrite和readonly
    3. 內(nèi)存管理 - assign训枢,strong,weak忘巧,copy恒界,unsafe_unretained
    4. set,get方法
  2. weak和assign的區(qū)別
    1. Weak修飾對(duì)象砚嘴,對(duì)象釋放后仗处,引用計(jì)數(shù)為0眯勾,對(duì)象會(huì)被置為nil。
    2. assign修飾基本數(shù)據(jù)類(lèi)型婆誓,如果用assign修飾對(duì)象吃环,對(duì)象釋放后,引用計(jì)數(shù)為0后洋幻,對(duì)象會(huì)變成野指針郁轻,容易崩潰。為什么基本數(shù)據(jù)類(lèi)型不會(huì)文留,因?yàn)榛緮?shù)據(jù)類(lèi)型是在棧上面好唯,不是在堆上面的。
  3. copy和strong
    1. 不可變使用copy燥翅,可變使用strong

不可變使用strong的例子

@property (nonatomic, strong) NSString *strongStr;
- (void)testStrCopy {
    NSString *tempStr = @"123";
    NSMutableString *mutString = [NSMutableString stringWithString:tempStr];
    self.strongStr = mutString;  // 子類(lèi)初始化父類(lèi)
    NSLog(@"self str = %p  mutStr = %p",self.strongStr,mutString);   // 兩者指向的地址是一樣的
    [mutString insertString:@"456" atIndex:0];
    NSLog(@"self str = %@  mutStr = %@",self.strongStr,mutString);  // 兩者的值都會(huì)改變,不可變對(duì)象的值被改變
    /*
     self str = 0x281806520  mutStr = 0x281806520
     self str = 456123  mutStr = 456123
     */
}

可變使用copy的例子

@property (nonatomic, copy) NSMutableString *mutString;
- (void)testStrCopy {
    NSString *str = @"123";
    self.mutString = [NSMutableString stringWithString:str];
    /*
    // 首先聲明一個(gè)臨時(shí)變量 NSMutableString *tempString = [NSMutableString stringWithString:str]; 
    // 將該臨時(shí)變量copy骑篙,賦值給self.mutString self.mutString = [tempString copy];
    通過(guò)[tempString copy]得到的self.mutString是一個(gè)不可變對(duì)象
    */
    NSLog(@"str = %p self.mutString = %p",str,self.mutString); // 兩者的地址不一樣
    [self.mutString appendString:@"456"]; // 會(huì)崩潰,因?yàn)榇藭r(shí)self.mutArray是NSString類(lèi)型森书,是不可變對(duì)象
}

可變對(duì)象的copy靶端、mutableCopy,可以看到,只要是可變對(duì)象凛膏,無(wú)論是集合對(duì)象杨名,還是非集合對(duì)象,copy和mutableCopy都是深拷貝猖毫。

- (void)testMutableCopy
{
    NSMutableString *str1 = [NSMutableString stringWithString:@"abc"];
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);
    
    NSMutableArray *array1 = [NSMutableArray arrayWithObjects:@"a",@"b", nil];
    NSArray *array2 = [array1 copy];
    NSMutableArray *array3 = [array1 mutableCopy];
    NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}

2018-12-13 19:12:44.287404+0800 testcopy[2654:1672606] str1 = 0x28020fba0 str2 = 0x92e1881c542bdf17 str3 = 0x28020f780
2018-12-13 19:12:44.287475+0800 testcopy[2654:1672606] array1 = 0x28020f8d0 array2 = 0x280c5e780 array3 = 0x28020fa20

不可變對(duì)象的copy台谍、mutableCopy,不可變對(duì)象的copy是淺拷貝,mutableCopy是深拷貝吁断。以NSString和NSArray為例趁蕊,測(cè)試代碼如下:

- (void)testCopy
{
    NSString *str1 = @"123";
    NSString *str2 = [str1 copy];
    NSMutableString *str3 = [str1 mutableCopy];
    NSLog(@"str1 = %p str2 = %p str3 = %p",str1,str2,str3);
    
    NSArray *array1 = @[@"1",@"2"];
    NSArray *array2 = [array1 copy];
    NSMutableArray *array3 = [array1 mutableCopy];
    NSLog(@"array1 = %p array2 = %p array3 = %p",array1,array2,array3);
}
2018-12-13 19:14:27.982467+0800 testcopy[2656:1673120] str1 = 0x102fc8078 str2 = 0x102fc8078 str3 = 0x280558f00
2018-12-13 19:14:27.982529+0800 testcopy[2656:1673120] array1 = 0x280b09ea0 array2 = 0x280b09ea0 array3 = 0x280558fc0

自定義對(duì)象如何支持copy:

自定義對(duì)象遵守NSCopying協(xié)議,且實(shí)現(xiàn)copyWithZone方法仔役,NSCopying是系統(tǒng)方法掷伙,直接使用即可。

@interface Student : NSObject <NSCopying> 
{ 
    NSString *_sex; 
} 
@property (atomic, copy) NSString *name; 
@property (nonatomic, copy) NSString *sex; 
@property (nonatomic, assign) int age; @end


- (instancetype)initWithName:(NSString *)name age:(int)age sex:(NSString *)sex
{
    if(self = [super init]){
        self.name = name;
        _sex = sex;
        self.age = age;
    }
    return self;
}

- (instancetype)copyWithZone:(NSZone *)zone
{
    // 注意骂因,copy的是自己,因此使用自己的屬性
    Student *stu = [[Student allocWithZone:zone] initWithName:self.name age:self.age sex:_sex];
    return stu;
}

輸出

- (void)testStudent
{
    Student *stu1 = [[Student alloc] initWithName:@"Wang" age:18 sex:@"male"];
    Student *stu2 = [stu1 copy];
    NSLog(@"stu1 = %p stu2 = %p",stu1,stu2);
}
stu1 = 0x600003a41e60 stu2 = 0x600003a41fc0
//深復(fù)制赃泡,因?yàn)槭莾?nèi)存復(fù)制寒波,copyWithZone,而不是直接內(nèi)存地址指向升熊。

來(lái)源:iOS面試之@property

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末俄烁,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子级野,更是在濱河造成了極大的恐慌页屠,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,561評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異辰企,居然都是意外死亡风纠,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén)牢贸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)竹观,“玉大人,你說(shuō)我怎么就攤上這事潜索〕粼觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,162評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵竹习,是天一觀(guān)的道長(zhǎng)誊抛。 經(jīng)常有香客問(wèn)我,道長(zhǎng)整陌,這世上最難降的妖魔是什么拗窃? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,470評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮蔓榄,結(jié)果婚禮上并炮,老公的妹妹穿的比我還像新娘。我一直安慰自己甥郑,他們只是感情好逃魄,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評(píng)論 6 385
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著澜搅,像睡著了一般伍俘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上勉躺,一...
    開(kāi)封第一講書(shū)人閱讀 49,806評(píng)論 1 290
  • 那天癌瘾,我揣著相機(jī)與錄音,去河邊找鬼饵溅。 笑死妨退,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜕企。 我是一名探鬼主播咬荷,決...
    沈念sama閱讀 38,951評(píng)論 3 407
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼轻掩!你這毒婦竟也來(lái)了幸乒?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,712評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤唇牧,失蹤者是張志新(化名)和其女友劉穎罕扎,沒(méi)想到半個(gè)月后聚唐,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡腔召,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評(píng)論 2 327
  • 正文 我和宋清朗相戀三年杆查,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宴咧。...
    茶點(diǎn)故事閱讀 38,643評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡根灯,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出掺栅,到底是詐尸還是另有隱情烙肺,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評(píng)論 4 330
  • 正文 年R本政府宣布氧卧,位于F島的核電站桃笙,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏沙绝。R本人自食惡果不足惜搏明,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望闪檬。 院中可真熱鬧星著,春花似錦、人聲如沸粗悯。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,745評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)样傍。三九已至横缔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衫哥,已是汗流浹背茎刚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,983評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留撤逢,地道東北人膛锭。 一個(gè)月前我還...
    沈念sama閱讀 46,351評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像蚊荣,于是被迫代替她去往敵國(guó)和親初狰。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評(píng)論 2 348

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