Objective-C---8---@property KVC

1. @property:

1.1. 屬性的聲明及實現:

之前的@property只是負責setter和getter的聲明,需程序員手動實現方法 :

           @property int age;   @synthesize age = _age;

現在的@property會生成實例變量及setter和getter方法的聲明及實現

// 聲明的時候:
@interface Person : NSObject
{
    int _age;
    int _height;
    double _weight;
    NSString *_name;
    
}
@property int age;

@property int height;
@property double weight;
@property (copy)NSString *name;

@end

// 實現的時候:

@implementation Person

// @synthesize會自動實現setter和getter方法
@synthesize age = _age; // 會自動訪問_age
@synthesize name = _name;
@synthesize height = _height;
@synthesize weight = _weight;

@end

 會完成三件事:

        1--聲明setter和getter方法

        2--生成成員變量(不需要在聲明成員變量啦~ ~)

        3--實現setter和getter方法
 
  因爲@property生成的成員變量是私有的,子類不能直接訪問,只能通過setter和getter方法訪問
 
 自己聲明的成員變量默認是protected,子類可以訪問

 可以將類型一致的寫在同一行,用逗號隔開。(儘量不要寫在一行)

  若是在.h 文件中沒有聲明任何成員變量,@synthesize age = _age 訪問_age時,若不存在,會自動生成一個成員變量_age;可見度爲@private

1.2.  屬性的屬性/@property的參數:

1.2.1. 有三大類:原子屬性,讀寫屬性,set方法處理

1. 原子屬性:

               atomic:對屬性加鎖,多線程下線程安全,默認值,速度比nonatomic慢

               nonatomic:對屬性不加鎖,多線程下不安全,但是速度快 (就是普通的setter getter方法)

2. 讀寫屬性:

              readwrite:生成getter、setter,默認值

              readonly:只生成getter方法

3. set方法處理:

                  assign:直接賦值,默認值(非對象類型:基本數據類型使用)

                  retain:先release原來的值,再retain新值(在一個類中有關聯其他對象的時候,OC對象類型:NSString,NSArray...使用)- - -內存優化 

                  copy:先release原來的值,再copy新值(所有遵守NSCopying協議的對象使用)- - -內存優化

assign實際生成的setter方法如下:(直接賦值)

- (void)setName:(NSString *)name{
    _name = name;
}
retain實際生成的setter方法如下:

- (void)setName:(NSString *)name{
    if(_name != name){
        [_name release];
        _name = [name retain];
    }
}
copy實際生成的setter方法如下:

- (void)setName:(NSString *)name{
    if(_name != name){
        [_name release];
        _name = [name copy];
    }
}
其他對象類型使用retain      NSString,block使用copy吧

在@property後面加屬性setter getter 相當於給系統生成的setter和getter方法重命名而已:

@property (nonatomic,assign,setter=isVip:,getter=isVip);

1.2.2. copy和retain的區別:

  @property (nonatomic,retain)NSString *name:

       retain是在你聲明的字符串上進行修改,下面的例子:第一次將str賦給t.name後,對str進行修改,即使不用再次賦值,t.name的內容也會跟着str改變

@autoreleasepool {
        Teacher *t = [[Teacher alloc] init];
        NSMutableString *str = [NSMutableString string];
        [str appendString:@"豬八戒"];
        t.name = str;
        [str appendString:@"二師兄"];
        NSLog(@"%@",t.name);
        [t release];
    }
結果打印顯示:

2015-10-07 11:29:43.588 Lesson-OC-8-Property[624:61344] 豬八戒二師兄
Program ended with exit code: 0
   @property (nonatomic,copy)NSString *name:

    copy是先拷貝一份str的內容,賦值給t.name,然後對str進行修改的時候,並不會影響t.name的值

@autoreleasepool {
        Teacher *t = [[Teacher alloc] init];
        NSMutableString *str = [NSMutableString string];
        [str appendString:@"豬八戒"];
        t.name = str;
        [str appendString:@"二師兄"];
        NSLog(@"%@",t.name);
        [t release];
    }
結果打印顯示:

2015-10-07 11:38:11.722 Lesson-OC-8-Property[691:64925] 豬八戒
Program ended with exit code: 0

2. KVC(key value coding):鍵值編碼

KVC是一種間接訪問實例變量的方法。

KVC操作方法由NSKeyValueCoding協議提供:

NSObject實現了這個協議,也就是OC中所有的類都支持KVC操作

2.1. 常用的KVC操作方法:

      動態設置(修改值):

              setValue:屬性值 forKey:屬性名 (用於簡單的路徑)

              setValue:屬性值 forKeyPath:屬性路徑 (用於複合路徑)---類.類.屬性

      動態讀取(獲取值):

              valueForKey:屬性名

              valueForKeyPath:屬性名

2.2. KVC查找規則: 

     動態設置屬性:

          優先考慮調用setter,沒有該方法則搜索_age成員變量,如果還是沒有,則調用:setValue: forUndefinedKey:方法

    動態讀取屬性:

          優先考慮調用age的getter方法,沒有該方法則搜索_age成員變量,如果還是沒有,則調用:valueForUndefinedKey:方法

   注:無論這些方法是私有還是其他,均可正常訪問

@autoreleasepool {
        Person *p = [[Person alloc] init];
//        p.name = @"Henry";
        // 訪問私有變量age:---動態設置(簡單路徑)
        [p setValue:@"Henry" forKey:@"name"]; // 給name賦值爲@"Henry"
        [p setValue:@"male" forKey:@"sex"];
        [p setValue:@28 forKey:@"age"];// 在本題中age是私有變量,但是通過這個方法是可以給age賦值的!!!
        [p showMessage];// 這個方法用來顯示name sex age
        NSLog(@"%@", [p valueForKey:@"name"]);
        
        
        Account *account1 = [[Account alloc] init];
        [p setValue:account1 forKey:@"account"];
        p.account.balance = 10.8;
        
//@"account.balance"是因爲Person類裏包含了實例變量Account *account  要想給account裏的balance賦值,需要根據路徑找到它
        [p setValue:@10.09 forKey:@"account.balance"];
        NSLog(@"%.2f", [[p valueForKeyPath:@"account.balance"] floatValue]);
        
// setValuesForKeysWithDictionary:就是用來將一個字典進行賦值
        NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"Shelock", @"name", @"male", @"sex", @"26", @"age", nil];
         [p setValuesForKeysWithDictionary:dic];
        NSLog(@"%@", p);
        
        
         [p release];
        [account1 release];
    }



 

發佈了44 篇原創文章 · 獲贊 0 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章