简述
2.KVC: forKey、forKeyPath的区别,建议使用
KVC是Key Value Coding的简称,意思是键值编码。简要来说,KVC提供了一种在运行时而非编译时动态访问对象属性与成员变量的方式,也就是说,我们可以用字符串的内容作为属性名称或者成员变量名称进行访问。
使用
1.利用KVC可以随意修改一个对象的属性或者成员变量(私有的也可以修改)。
其中,key为被修改对象的名称或者其成员变量名称。
#import <UIKit/UIKit.h>
@interface MainTabBarController : UITabBarController
@end
@implementation MainTabBarController
- (void)viewDidLoad {
[super viewDidLoad];
// WTTabBar是自定义的tabBar,这里要修改系统空间为自定义tabBar
WTTabBar *myTabBar = [[WTTabBar alloc] init];
// self.myTabBar = tabBar; 这里会报错,原因myTabBar为readonly,所以这里考虑使用KVC。
[self setValue:myTabBar forKeyPath:@"tabBar"];
}
@end
2.KVC: forKey、forKeyPath的区别,建议使用forKeyPath
下面有两个示例类:
- Person类:name,age,dog及dogs四个属性;
- Dog类:name,number两个属性。
类:Person.h
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int age;
@property (nonatomic, strong) Dog *dog;
@property (nonatomic, strong) NSArray *dogs;
- (void)printHeight;
@end
#import "Person.h"
@implementation Person
{
@private
double _height; // 身高
}
@end
类Dog.h
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@property (nonatomic, copy) NSString *name; //名字
@property (nonatomic, assign) Int *number; //数量
@end
#import "Dog.h"
@implementation Dog
@end
使用KVC修改属性:
- (void)testKVC
{
Person *p = [[Person alloc] init];
// 1.property
p.name = @"小王";
p.age = 20;
p.dog = [[Dog alloc] init];
p.dog.name = "AA";
// 2.forkey
[p setValue:@"大王" forKey:@"name"];
[p setValue:@30 forKey:@"age"];
[p.dog setValue:@"BB" forKey:@"name"];
//Person对象的私有变量_height,对两个key:height\_height,任意一个key都可以修改其属性。
//(对于height,KVC先从内存中寻找对应名为height的属性,如果找不到就会自动寻找_height,然后进行相应的修改)
[p setValue:@1.80 forKey:@"height"];
[p setValue:@1.85 forKey:@"_height"];
// 3.forKeyPath
// forKeyPath包含了forKey的功能,以后使用forKeyPath就可以了。
// forKeyPath可以利用‘ . ’运算符一层一层往下查找对象的属性
[p setValue:@"老王" forKeyPath:@"p.name"];
[p setValue:@30 forKeyPath:@"p.age"];
[p setValue:@"CC" forKeyPath:@"dog.name"];
NSLog(@"%d %@", p.age, p.name);
}
3. KVC取值
- (void)useKVCGetValue
{
Person *p = [[Person alloc] init];
p.dog = [[Dog alloc] init];
[p setValue:@"妞妞" forKeyPath:@"dog.name"];
NSLog(@"%@", [p valueForKeyPath:@"dog.name"]);
}
总结
- key的值必须正确,如果拼写错误,会出现异常;
- valueForKey\ valueForKeyPath 方法根据key的值读取对象的属性,setValue:forKey:\ forKeyPath: 是根据key的值来写对象的属性;
- 推荐使用 valueForKeyPath \ setValue:forKeyPth;
- 当key的值是没有定义的,valueForUndefinedKey:这个方法会被调用,如果重写了这个方法,就可以获取错误的key值。