天天看點

8、屬性

屬性

為執行個體變量提供了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:

繼續閱讀