屬性
為執行個體變量提供了setter、getter⽅法的預設實作
能在⼀定程度上簡化程式代碼,并且增強執行個體變量的通路安全性
聲明:@property
@property是編譯器指令,自動聲明set/get方法
@property NSString *name;//寫在.h檔案中
相當于@interface中聲明了兩個⽅法(setter、getter):
- (void)setName:(NSString *)name;
- (NSString *)name;
注意:
- @property隻能寫在@interface @end中
- (xcode4.4之前)@property用來自動生成成員變量的set/get方法聲明
- 告訴property要生成的get/set方法聲明的成員變量類型是什麼
- 告訴property要生成的set/get方法是什麼屬性的,屬性名稱去掉下劃線
實作:@synthesize
@synthesize name ;//寫在.m檔案中
相當于@implementation實作了setter、getter
- (void)setName:(NSString *)name
{
self->name = name;//此時變量名為name,而不是我們常用的_name
}
- (NSString *)name
{
return name;//此時變量名為name,而不是我們常用的_name
}
注意:方法名(name)一定要現在.h中使用@property NSString * name 進行聲明
@synthesize指定執行個體變量指派
@synthesize name = _name;//表示用a的get和set方法,修改屬性b的值
相當于
- (void)setName:(NSString *)name
{
_name = name;
}
- (NSString *)name
{
return _name;
}
屬性的屬性(Attribute)
@property的增強使用
- xcode4.4之後可以隻使用@property而不使用@synthesize
- 聲明和實作了_age,_name
讀寫性控制
readonly
隻聲明getter⽅法(⽆setter⽅法)
@property(readonly)NSString *name;//等價于 - (NSString *)name;
readwrite(預設)
既聲明setter⼜聲明getter。
@property(readwrite)NSString *name;
//等價于
- (NSString *)name;
- (void)setName:(NSString *)name;
原⼦性控制
程式開發過程中,setter、getter處處都在⽤,如果使⽤atomic,需要不斷的對setter、getter加鎖解鎖以保證線程通路安全,會很占⽤系統資源,降低
系統性能。
通常設定為nonatomic,某些屬性需要線程安全的時候,才定義為atomic。
@property (readwrite,nonatomic)NSString *name;
//等價于
- (NSString *)name;
- (void)setName:(NSString *)name;
atomic(預設)
setter、getter⽅法在多線程通路下是絕對安全的,即setter、getter内部做了多線程通路處理
nonatomic
setter、getter⽅法内部不會做多線程通路處理,僅僅是普通的setter、getter⽅法
語義設定
- 如果屬性是⾮對象類型(⽐如int,float等)屬性的語義設定使⽤assign
- 如果屬性是對象類型(⽐如NSStrng、NSArray等)屬性的語義設定使⽤retain
- 如果屬性是對象類型并且想得到參數的copy,使⽤copy關鍵字
assign
setter、getter内部實作是直接指派。
@property(nonatomic,assign)NSString *name;
//等價于
- (void)setName:(NSString *)name{
_name = name;
}
- (NSString *)name{
return _name;
}
retain
setter、getter的内部實作會做記憶體優化
:@property(nonatomic,retain)NSString *name;
//等價于
- (void)setName:(NSString *)name{
if(_name != name){
[_name release];
_name = [name retain];
}
}
- (NSString *)name{
return [[_name retain]autorelease];
}
copy
setter、getter的内部實作也會做記憶體優化
@property(nonatomic,copy)NSString *name;
//等價于
- (void)setName:(NSString *)name{
if(_name != name){
[_name release];
_name = [name copy];
}
}
- (NSString *)name{
return [[_name retain]autorelease];
}
點文法
⼀種便捷的屬性通路⽅式,是編譯器的特性,即編譯器(XCode)幫我們做代碼替換
凡是符合系統預設setter、getter書寫格式的⽅法都可以使⽤點文法。
[person1 setName:@”zhangsan”];//等價于person1.name = @”zhangsan”;
NSString *name = [person1 name];//可以等價寫成NSString *name = person1.name;
點文法:對象.屬性名并不是直接通路執行個體變量,而是xcode看到點文法後會替換成set或get方法,
在等号左側(設定值)為set方法,在等号右側(擷取值)為get方法
點文法注意事項
-
set方法裡不能用點文法,他會造成死循環
-(void)setAge:(int)age{
self.age = age;//self.age會遞歸調用set方法,造成死循環
}
- get方法裡不能return點文法,因為return self.age會造成死循環
- 如果程式中不存在get+set方法,點文法是不可用的
KVC
KVC(Key-Value-Coding),鍵值編碼,是⼀種間接通路執行個體變量的⽅法。
key:鍵,⽤于辨別執行個體變量
vlaue:執行個體變量對應的值
//注意:當key不存在的時候,會執⾏setValue:forUndefinedKey:
系統預設實作是抛出⼀個異常
修改值
setValue:forKey:
setValue:forKeyPath:
setValue:forUndefinedKey:
setValuesForKeysWithDictionary:
擷取值
valueForKey:
valueForKeyPath:
valueForUndefinedKey: