iOS之KVC

KVC(Key-value coding)鍵值編碼,就是指iOS的開發中,可以允許開發者通過Key名直接訪問對象的屬性,或者給對象的屬性賦值。而不需要調用明確的存取方法。這樣就可以在運行時動態地訪問和修改對象的屬性。而不是在編譯時確定,這也是iOS開發中的黑魔法之一。

 

賦值過程:

1. 先找相關方法 set<key>: ,  _set<key>: , setIs<key>: ;

2.若沒有相關方法,則會調用+(BOOL)accessInstanceVariablesDirectly (判斷是否可以直接訪問變量)。

    如果:NO,  那麼直接執行KVC 的 setValue:forUndefinedKey方法(系統異常,未定義key)。

    如果:  YES, 你什麼繼續尋找相關變量 _<key> ,   _is<key> ,   <key>  , is<key>。

3.若方法或者成員變量都不存在,則執行 setValue:forUndefindKey 方法,(默認拋出異常)。

4 如果賦值對象爲nil , 則會調用setNilValueForKey:,  (拋出異常)

 

取值過程:

1. 先找相關方法 get<key>: , <key>

2.若沒有相關方法,則會調用+(BOOL)accessInstanceVariablesDirectly (判斷是否可以直接訪問變量)。

    如果:NO,  那麼直接執行KVC 的 value:forUndefinedKey方法(系統異常,未定義key)。

    如果:  YES, 你什麼繼續尋找相關變量 _<key> ,   _is<key> ,   <key>  , is<key>。

3.若方法或者成員變量都不存在,則執行 value:forUndefindKey 方法,(默認拋出異常)。

 

異常處理:

1.  setNilValueForKey:            賦值爲空

2. (set)value:forUndefindKey       Key值不存在

 

正確性驗證:

調用 vaildateValue  返回bool, 工作原理如下:

  1. 先找要驗證的類中是否實現了方法-(BOOL)validate<key>:error: (此方法去驗證要要爭的對象的正確性)。
  2 如果沒有實現 -(BOOL)validate<key>:error 方法。 系統默認返回YES.

 

消息傳遞:

    NSArray* arr = @[@"Monday", @"Tuesday", @"Wednesday"];
    NSArray* lengthArr = [arr valueForKey:@"length"];
    NSLog(@"每個元素的長度%@", lengthArr);
    
    
    NSArray* lowercaseArr = [arr valueForKey:@"lowercaseString"];
    NSLog(@"每個元素轉小寫%@", lowercaseArr);

  聚合操作符:

 @avg、@count、@max、@min、@sum

    NSMutableArray* students = [NSMutableArray array];
    for (int i = 0; i < 6; i++) {
        TZPerson* student = [TZPerson new];
        NSDictionary* dict = @{
                               @"name":@"Tom",
                               @"age":@(18+i),
                               @"nick":@"Cat",
                               @"height":@(1.65 + 0.02*arc4random_uniform(6)),
                               };
        [student setValuesForKeysWithDictionary:dict];
        [students addObject:student];
    }
    
    NSLog(@"%@", [students valueForKey:@"height"]);
    
    /// 平均身高
    float avg = [[students valueForKeyPath:@"@avg.height"] floatValue];
    NSLog(@"%f", avg);

   數組操作符:

   去重 /不去重   @distinctUnionOfObjects @unionOfObjects

    NSMutableArray* students = [NSMutableArray array];
    for (int i = 0; i < 6; i++) {
        TZPerson* student = [TZPerson new];
        NSDictionary* dict = @{
                               @"name":@"Tom",
                               @"age":@(18+i),
                               @"nick":@"Cat",
                               @"height":@(1.65 + 0.02*arc4random_uniform(6)),
                               };
        [student setValuesForKeysWithDictionary:dict];
        [students addObject:student];
    }
    
    NSLog(@"%@", [students valueForKey:@"height"]);
    
    
    NSArray* arr = [students valueForKeyPath:@"@distinctUnionOfObjects.height"];
    NSLog(@"arr = %@", arr);
    
    NSArray* arr1 = [students valueForKeyPath:@"@unionOfObjects.height"];
    NSLog(@"arr1 = %@", arr1);

嵌套集合(array&set)操作

@distinctUnionOfArrays @unionOfArrays     @distinctUnionOfSets(針對set)


    NSMutableArray* students = [NSMutableArray array];
    for (int i = 0; i < 6; i++) {
        TZPerson* student = [TZPerson new];
        NSDictionary* dict = @{
                               @"name":@"Tom",
                               @"age":@(18+i),
                               @"nick":@"Cat",
                               @"height":@(1.65 + 0.02*arc4random_uniform(6)),
                               };
        [student setValuesForKeysWithDictionary:dict];
        [students addObject:student];
    }
    
    NSMutableArray* students1 = [NSMutableArray array];
    for (int i = 0; i < 6; i++) {
        TZPerson* student = [TZPerson new];
        NSDictionary* dict = @{
                               @"name":@"Tom",
                               @"age":@(18+i),
                               @"nick":@"Cat",
                               @"height":@(1.65 + 0.02*arc4random_uniform(6)),
                               };
        [student setValuesForKeysWithDictionary:dict];
        [students1 addObject:student];
    }
    
    // 嵌套數組
    NSArray* nestArr = @[students, students1];
    
    
    NSArray* arr = [nestArr valueForKeyPath:@"@distinctUnionOfArrays.height"];
    NSLog(@" 二維數組合並去重arr = %@", arr);
    
    NSArray* arr1 = [nestArr valueForKeyPath:@"@unionOfArrays.height"];
    NSLog(@"二維數組合不去重arr1 = %@", arr1);

集合代理對象 (一對多)

// .h
@interface TZPerson : NSObject

@property (nonatomic, strong) NSString* name;

@property (nonatomic, assign) int age;

@property (nonatomic, strong) NSString* nick;

@property (nonatomic, assign) float height;


@property (nonatomic, assign) NSUInteger count;

@property (nonatomic, strong) NSMutableArray *penArr;

@end



//.m


@implementation TZPerson


- (NSUInteger) countOfBooks {
    return self.count;
}

- (id) objectInBooksAtIndex:(NSUInteger)index {
    return [NSString stringWithFormat:@"book %lu", index];
}

// 個數
- (NSUInteger) countOfPens {
    return [self.penArr count];
}

// 是否包含這個成員對象
- (id) memberOfPens:(id)object {
    return [self.penArr containsObject:object] ? object : nil;
}

// 迭代器
- (id) enumeratorOfPens {
    return [self.penArr reverseObjectEnumerator];
}

@end



// ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    TZPerson* p = [TZPerson new];
    p.count = 5;
    
    NSLog(@"books = %@", [p valueForKey:@"books"]);
    
    p.penArr = [NSMutableArray arrayWithObjects:@"pen0", @"pen1", @"pen2", @"pen3", nil];
    NSSet* set = [p valueForKey:@"pens"];
    NSLog(@"pens = %@", set);
    
    NSEnumerator* enumerator = [set objectEnumerator];
    NSString* str = nil;
    while (str = [enumerator nextObject]) {
        NSLog(@"%@", str);
    }
}

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章