欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

KVC、KVO探识(一)KVO和KVO的详细使用

程序员文章站 2024-03-24 14:04:28
...

前言

最近一直在做原型图,中间有两天没有写简书了。感觉心里面特别不是滋味。所以今天好不容易忙中偷闲,所以今天必须写几篇简书,安慰一下自己的内心。于是今天给大家分享一下KVC和KVO的简单用法,随后会更加深层次的去写一系列的简书,去深层次的讲解KVC和KVO。

KVC用法

KVC也就是key-value-coding(键值编码),简而言之就是通过key值去进行赋值和取值。主要是是操作对象的属性。以下是几个常用的方法:

  • setValue:forKey:(为对象的属性赋值)
  • setValue: forKeyPath:(为对象的属性赋值(包含了setValue:forKey:的功能,并且还可以对对象内的类的属性进行赋值))
  • valueForKey:(根据key取值)
  • valueForKeyPath:(根据keyPath取值)
  • setValuesForKeysWithDictionary:(对模型进行一次性赋值)

几种方法的详尽用法

例如:生成一个这样子的对象Person
person.h

 

@class Car;
@interface Person : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,strong)Car *car;
@end

Car.h

 

@interface Car : NSObject
@property (nonatomic,strong) NSNumber *price;
@end

在ViewController.m中调用
ViewController.m

 

- (void)viewDidLoad {
      [super viewDidLoad];
      Person *person=[[Person alloc]init];
      [person setValue:@"lxh" forKey:@"name"];
      float price=100.0;
      Car *car=[[Car alloc]init];
      person.car=car;
      [person setValue:[NSNumber numberWithFloat:price] forKeyPath:@"car.price"];
      NSLog(@"%@",person.name);

      NSLog(@"%f",car.price.floatValue);
}

有几个小点,我也是在敲代码的时候发现的。

  • 在Person中我仅仅只是声明了@class Car,而没有引用#import "Car.h",然后在ViewController.m中便可以对其进行: [person setValue:[NSNumber numberWithFloat:price] forKeyPath:@"car.price"];这样子的赋值。所以说明KVC会去自动查找Car类进行赋值。
  • 在对person.car进行赋值的时候,必须保证car变量的存在,也就是说,必须生成一个Car对象赋值给person.car.否则会抛出野指针异常错误。
  • 还有就是setValue:forKey:和setValue: forKeyPath:这两个方法,可以查看NSObject中的声明:- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;你会发现value的值必须是id,也就是说不能传基本数据类型,必须是指针类型的变量。

KVC和对象的setter、getter方法的区别

一般情况下,KVC和setter、getter应该说都能达到对对象属性的赋值,并且KVC操作也是去调用的setter方法和getter方法(针对一些已经在.h中声明的属性而言)。但是对于一些私有属性,那么这个时候setter、getter方法就没有用了,这个时候KVC却能发挥重要优势。
例如:在Person.m中
#import "Person.h"
@implementation Person
{
NSInteger _height;
}
@end
此时你会发现setter、getter已经无能为力了,但是KVC去可以实现赋值、取值

 

[p setValue:@170 forKey:@"height"];

key和keyPath的区别

keyPath方法是集成了key的所有功能,也就是说对一个对象的一般属性进行赋值、取值,两个方法是通用的,都可以实现。但是对对象中的对象进的属性行赋值,只有keyPath能够实现。

setValuesForKeysWithDictionary:的巧妙使用(字典转模型)

 

-(instancetype)initWithDict:(NSDictionary *)dict{
         if (self = [super init]) {
               [self setValuesForKeysWithDictionary:dict]; 
          } 
         return self;
}

注意点:

  • 字典转模型的时候,字典中的某一个key一定要在模型中有对应的属性
  • 如果一个模型中包含了另外的模型对象,是不能直接转化成功的。
  • 通过kvc转化模型中的模型,也是不能直接转化成功的。

KVO的用法

KVO也就是key-value-observing(即键值观察),利用一个key来找到某个属性并监听其值得改变。用法如下:

  • 添加观察者
  • 在观察者中实现监听方法,observeValueForKeyPath: ofObject: change: context:(通过查阅文档可以知道,绝大多数对象都有这个方法,因为这个方法属于NSObject)
  • 移除观察者

 

//让对象b监听对象a的name属性
//options属性可以选择是哪个
 /* NSKeyValueObservingOptionNew =0x01, 新值 
  * NSKeyValueObservingOptionOld =0x02, 旧值 
  */ 
[a addObserver:b forKeyPath:@"name"options:kNilOptionscontext:nil]; 
a.name = @"zzz";
#pragma mark - 实现KVO回调方法
/* * 当对象的属性发生改变会调用该方法
    * @param keyPath 监听的属性 
    * @param object 监听的对象 
    * @param change 新值和旧值 
    * @param context 额外的数据 
*/
- (void)observeValueForKeyPath:(NSString *)keyPathofObject:(id)objectchange:(NSDictionary<NSString *,id>*)change context:(void *)context{ 
    NSLog(@"%@的值改变了,",keyPath); 
    NSLog(@"change:%@", change);
}
//最后不要忘记了,去移除observer
- (void)dealloc{ 
       [a removeObserver:b forKeyPath:@"name"];
  }

KVO底层(这部分涉及到了runtime,关于isa指针,会在随后的简述中介绍)

当一个类的属性被观察的时候,系统会通过runtime动态的创建一个该类的派生类,并且会在这个类中重写基类被观察的属性的setter方法,而且系统将这个类的isa指针指向了派生类,从而实现了给监听的属性赋值时调用的是派生类的setter方法。重写的setter方法会在调用原setter方法前后,通知观察对象值得改变。
  具体实现图如下,这里我拿的是iOS程序猿的图,借用一下应该没关系吧?

KVC、KVO探识(一)KVO和KVO的详细使用

 

今天仅仅是KVO和KVC的简单的用法的介绍,随后会更加深层次的进行介绍,敬请期待.....、

欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!



作者:Peak_One
链接:https://www.jianshu.com/p/ca5cf1610d34
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关标签: iOS基础