kvc
是key value coding的缩写,即:键值编码。键值编码提供了非常强大的功能:只要存在访问器方法(set,get方法)、声明属性或实例变量,就可以将其名字指定为字符串来访问。
// 返回表示属性的键字符串对应的值
- (id)valueForKey:(NSString *)key;
Person *p1 = [[Person alloc] init];// 给Person类的实例p1的name属性赋值[p1 setValue:@"张三" forKey:@"name"];// 获取Person类的实例p1的name属性的值 NSString *name = [p1 valueForKey:@"name"];
// 将键字符串key所对应的属性的值设置为value
- (void)setValue:(id)value forKey:(NSString *)key;
// p1是Person类的对象,name是Person类的一个属性Person *p1 = [[Person alloc] init]; [p1 setValue:@"张三" forKey:@"name"];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 以点“.”切分键路径,并使用第一个键像接收器发送valueForKey:方法,然后在使用路径的下一个键,向得到的对象发送valueForKey:fangfa,如此反复操作,返回最后获得的对象。
- (id)valueForKeyPath:(NSString *)keyPath;
// 与valueForKeyPath:方法同样取出对象,这里只对路径中的最后一个键调用setValue:ForKey:方法,并设置属性值为value。
- (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
例:
Dog类:
@interface Dog: NSObject// 狗的品种@property (nonatomic, copy) NSString *name;@end
Person类:
#import#import "Dog.h"@interface Person : NSObject// 姓名@property (nonatomic, copy) NSString *name;// 年龄@property (nonatomic, assign) int age;// 电子邮件@property (nonatomic, copy) NSString *email;@property (nonatomic, strong) Dog *dog;@end
main函数:
#import#import "Person.h"int main(int argc, const char * argv[]) { @autoreleasepool { Person *p1 = [[Person alloc] init]; // @"dog.name" 这个就叫做keyPath 或者叫 "属性的路径" [p1 setValue:@"哈士猫" forKeyPath:@"dog.name"];
NSString *dogName = [p1 valueForKeyPath:@"dog.name"];// 等同于 [[p1 valueForKey:@"dog"] valueForKey:@"name"];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// 根据字典的键,找对应的属性,为属性赋值(字典转模型)
- (void)setValuesForKeysWithDictionary:(NSDictionary *)keyedValues;
#import#import "Person.h"int main(int argc, const char * argv[]) { @autoreleasepool { Person *p1 = [[Person alloc] init]; NSDictionary *bz = @{ @"name" : @"小明", @"age" : @28, @"email" : @"rzc0714@163.com", @"dog" : @{@"name" : @"加肥猫"} }; [p1 setValuesForKeysWithDictionary:bz];
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// 把对象转成字典
- (NSDictionary *)dictionaryWithValuesForKeys:(NSArray *)keys;
// 把对象转成字典NSDictionary *dict = [p1 dictionaryWithValuesForKeys:@[@"name", @"age", @"email", @"dog"]];
kvo
kvo(键值观察):当某对象的某个属性的值改变时可以实时监听到
注:只有遵循 KVO 变更属性值的方式才会执行 KVO 的回调方法,例如是否执行了 setter 方法、或者是否使用了 KVC 赋值
例如:// 注册观察者/*Observer:观察者(监听着)keyPath:监听那个属性options:监听新值的改变 */[rightView addObserver:self forKeyPath:@“frame” options:NSKeyValueObservingOptionNew context:nil];// 观察者处理回调/*keyPath:属性名称object:被观察的对象change:变化前后的值都存储在 change 字典中context:注册观察者时,context 传过来的值 */- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDcitionary *)change context:(void *)context{ //只要上面监听的属性的值一发生变化就会调用这个方法 }// 注意:kvo监听的对象在销毁时要同时销毁观察者,否则会崩掉-(void)dealloc{ [rightView removeObserver:self forKeyPath:@“frame”];}
工作中遇到的使用性问题:NSMutableArray内容发生变化时监听
- (void)setSelected:(BOOL)selected animated:(BOOL)animated { [super setSelected:selected animated:animated]; if ([self.VC.selectedDeleteArr containsObject:self.waitChectModel] && !selected) { [[self.VC mutableArrayValueForKey:@"selectedDeleteArr"] removeObject:self.waitChectModel]; }else if (![self.VC.selectedDeleteArr containsObject:self.waitChectModel] && selected){ // 选中就放到数组中 [[self.VC mutableArrayValueForKey:@"selectedDeleteArr"] addObject:self.waitChectModel]; } }
遇到的坑就是不使用kvc([self.VC mutableArrayValueForKey:@"selectedDeleteArr"]),直接使用addObject方法,观察者回调方法是不会触发的(验证了上面kvo的触发条件)