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);
    }
}

 

 

 

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