定义LGPerson和LGStudent类
typedef struct {
float x, y, z;
} ThreeFloats;
@interface LGPerson : NSObject{
@public
NSString *myName;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) NSArray *array;
@property (nonatomic, strong) NSMutableArray *mArray;
@property (nonatomic, assign) int age;
@property (nonatomic) ThreeFloats threeFloats;
@property (nonatomic, strong) LGStudent *student;
@end
@interface LGStudent : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *subject;
@property (nonatomic, copy) NSString *nick;
@property (nonatomic, assign) int age;
@property (nonatomic, assign) int length;
@property (nonatomic, strong) NSMutableArray *penArr;
@end
一、KVC 的防问
调用一般的setter方法
LGPerson *person = [[LGPerson alloc] init];
person.name = @"LG_Cooci"; // setter -- llvm
person.age = 18;
person->myName = @"cooci";
NSLog(@"%@ - %d - %@",person.name,person.age,person->myName);
打印结果:
都赋值成功了
调用
setValue:forkey:方法
[person setValue:@"KC" forKey:@"name"];
同样可以设置成功
集合类的赋值
NSArray *array = [person valueForKey:@"array"];
array = @[@"100",@"2",@"3"];
[person setValue:array forKey:@"array"];
NSLog(@"%@",[person valueForKey:@"array"]);
给不可变数组赋值
NSMutableArray *mArray = [person mutableArrayValueForKey:@"array"];
[person mutableArrayValueForKey:@"array"];
mArray[0] = @"200";
NSLog(@"%@",[person valueForKey:@"array"]);
结结构体属性赋值
ThreeFloats floats = {1.,2.,3.};
NSValue *value = [NSValue valueWithBytes:&floats objCType:@encode(ThreeFloats)];
[person setValue:value forKey:@"threeFloats"];
NSValue *value1 = [person valueForKey:@"threeFloats"];
NSLog(@"%@",value1);
ThreeFloats th;
[value1 getValue:&th];
NSLog(@"%f-%f-%f",th.x,th.y,th.z);
使用setValue:forKeyPath:给模型属性的属性赋值
LGStudent *student = [LGStudent alloc];
student.subject = @"大师班";
person.student = student;
[person setValue:@"Swift" forKeyPath:@"student.subject"];
NSLog(@"%@",[person valueForKeyPath:@"student.subject"]);
数组的取值
- (void)arrayDemo{
LGStudent *p = [LGStudent new];
p.penArr = [NSMutableArray arrayWithObjects:@"pen0", @"pen1", @"pen2", @"pen3", nil];
NSArray *arr = [p valueForKey:@"penArr"]; // 动态成员变量
NSLog(@"pens = %@", arr);
//NSLog(@"%@",arr[0]);
NSLog(@"%d",[arr containsObject:@"pen9"]);
// 遍历
NSEnumerator *enumerator = [arr objectEnumerator];
NSString* str = nil;
while (str = [enumerator nextObject]) {
NSLog(@"%@", str);
}
}
字典与模型的相互转换
- (void)dictionaryTest{
NSDictionary* dict = @{
@"name":@"Cooci",
@"nick":@"KC",
@"subject":@"iOS",
@"age":@18,
@"length":@180
};
LGStudent *p = [[LGStudent alloc] init];
// 字典转模型
[p setValuesForKeysWithDictionary:dict];
NSLog(@"%@",p);
// 键数组转模型到字典
NSArray *array = @[@"name",@"age",@"nick",@"subject",@"length"];
NSDictionary *dic = [p dictionaryWithValuesForKeys:array];
NSLog(@"%@",dic);
}
setValuesForKeysWithDictionary:将字典转为对应的模型;dictionaryWithValuesForKeys:将模型转为字典.
KVC消息传递
- (void)arrayMessagePass{
NSArray *array = @[@"Hank",@"Cooci",@"Kody",@"CC"];
NSArray *lenStr= [array valueForKeyPath:@"length"];
NSLog(@"%@",lenStr);// 消息从array传递给了string
NSArray *lowStr= [array valueForKeyPath:@"lowercaseString"];
NSLog(@"%@",lowStr);
}
[array valueForKeyPath:@"length"]获取数组中字符串数据的长度;
[array valueForKeyPath:@"lowercaseString"]让数组中的字符串成员首字母小写.
这两个方法都实现了将消息从NSArray传递到他的NSString元素.
聚合操作符
- (void)aggregationOperator{
NSMutableArray *personArray = [NSMutableArray array];
for (int i = 0; i < 6; i++) {
LGStudent *p = [LGStudent new];
NSDictionary* dict = @{
@"name":@"Tom",
@"age":@(18+i),
@"nick":@"Cat",
@"length":@(175 + 2*arc4random_uniform(6)),
};
[p setValuesForKeysWithDictionary:dict];
[personArray addObject:p];
}
NSLog(@"%@", [personArray valueForKey:@"length"]);
/// 平均身高
float avg = [[personArray valueForKeyPath:@"@avg.length"] floatValue];
NSLog(@"%f", avg);
int count = [[personArray valueForKeyPath:@"@count.length"] intValue];
NSLog(@"%d", count);
int sum = [[personArray valueForKeyPath:@"@sum.length"] intValue];
NSLog(@"%d", sum);
int max = [[personArray valueForKeyPath:@"@max.length"] intValue];
NSLog(@"%d", max);
int min = [[personArray valueForKeyPath:@"@min.age"] intValue];
NSLog(@"%d", min);
}
- personArray中的元素是LGStudent对象;
[personArray valueForKey:@"length"]获取数组元素中的所有属性length的值;[personArray valueForKeyPath:@"@count.length"]获取属性length的个数、平均值、最大值、最小值和和。
数组操作符
- (void)arrayOperator{
NSMutableArray *personArray = [NSMutableArray array];
for (int i = 0; i < 6; i++) {
LGStudent *p = [LGStudent new];
NSDictionary* dict = @{
@"name":@"Tom",
@"age":@(18+i),
@"nick":@"Cat",
@"length":@(175 + 2*arc4random_uniform(6)),
};
[p setValuesForKeysWithDictionary:dict];
[personArray addObject:p];
}
NSLog(@"%@", [personArray valueForKey:@"length"]);
// 返回操作对象指定属性的集合
NSArray* arr1 = [personArray valueForKeyPath:@"@unionOfObjects.length"];
NSLog(@"arr1 = %@", arr1);
// 返回操作对象指定属性的集合 -- 去重
NSArray* arr2 = [personArray valueForKeyPath:@"@distinctUnionOfObjects.length"];
NSLog(@"arr2 = %@", arr2);
}
[personArray valueForKeyPath:@"@unionOfObjects.length"]返回操作对象指定属性的集合;[personArray valueForKeyPath:@"@distinctUnionOfObjects.length"]返回操作对旬指定属性的集合,会去重。
数组操作数组中元素某属性的操作符
- (void)arrayNesting{
NSMutableArray *personArray1 = [NSMutableArray array];
for (int i = 0; i < 6; i++) {
LGStudent *student = [LGStudent new];
NSDictionary* dict = @{
@"name":@"Tom",
@"age":@(18+i),
@"nick":@"Cat",
@"length":@(175 + 2*arc4random_uniform(6)),
};
[student setValuesForKeysWithDictionary:dict];
[personArray1 addObject:student];
}
NSMutableArray *personArray2 = [NSMutableArray array];
for (int i = 0; i < 6; i++) {
LGStudent *person = [LGStudent new];
NSDictionary* dict = @{
@"name":@"Tom",
@"age":@(18+i),
@"nick":@"Cat",
@"length":@(175 + 2*arc4random_uniform(6)),
};
[person setValuesForKeysWithDictionary:dict];
[personArray2 addObject:person];
}
// 嵌套数组
NSArray* nestArr = @[personArray1, personArray2];
NSArray* arr = [nestArr valueForKeyPath:@"@distinctUnionOfArrays.length"];
NSLog(@"arr = %@", arr);
NSArray* arr1 = [nestArr valueForKeyPath:@"@unionOfArrays.length"];
NSLog(@"arr1 = %@", arr1);
依旧可以取出
nestArr中两个元素personArray1和personArray2数组的元素的属性length的数组。
KVC的设值取值分析
设值分析
设值方法的调用顺序
[person setValue:@"LG_Cooci" forKey:@"name"]设值流程按如下顺序依次调用
先看
setName:有没有实现,再看_setName:有没有实现,再看setIsName:有没有实现,最后看_setIsName:有没有实现。
如果以上方法都没有实现,回查看:
+ (BOOL)accessInstanceVariablesDirectly{
return YES;
}
是否返回为NO,为NO则调用:
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
}
否则查找如下成员变量
直接通过成员变量查找的赋值流程
person->_name = @"_name";
person->_isName = @"_isName";
person->name = @"name";
person->isName = @"isName";
NSLog(@"取值:%@",[person valueForKey:@"name"]);
取值流程
- (NSString *)getName{
return NSStringFromSelector(_cmd);
}
- (NSString *)name{
return NSStringFromSelector(_cmd);
}
- (NSString *)isName{
return NSStringFromSelector(_cmd);
}
- (NSString *)_name{
return NSStringFromSelector(_cmd);
}
[person valueForKey:@"name"]查找成员变量的调用以上方法的顺序:
先调用
getName,再调用name,再调用isName,最后调用_name。