KVC、KVO探識(shí)(一)KVO和KVO的詳細(xì)使用

前言

最近一直在做原型圖,中間有兩天沒有寫簡(jiǎn)書了。感覺心里面特別不是滋味。所以今天好不容易忙中偷閑,所以今天必須寫幾篇簡(jiǎn)書,安慰一下自己的內(nèi)心。于是今天給大家分享一下KVC和KVO的簡(jiǎn)單用法,隨后會(huì)更加深層次的去寫一系列的簡(jiǎn)書,去深層次的講解KVC和KVO。

KVC用法

KVC也就是key-value-coding(鍵值編碼),簡(jiǎn)而言之就是通過key值去進(jìn)行賦值和取值。主要是是操作對(duì)象的屬性。以下是幾個(gè)常用的方法:

  • setValue:forKey:(為對(duì)象的屬性賦值)
  • setValue: forKeyPath:(為對(duì)象的屬性賦值(包含了setValue:forKey:的功能,并且還可以對(duì)對(duì)象內(nèi)的類的屬性進(jìn)行賦值))
  • valueForKey:(根據(jù)key取值)
  • valueForKeyPath:(根據(jù)keyPath取值)
  • setValuesForKeysWithDictionary:(對(duì)模型進(jìn)行一次性賦值)
幾種方法的詳盡用法

例如:生成一個(gè)這樣子的對(duì)象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中調(diào)用
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);
}

有幾個(gè)小點(diǎn),我也是在敲代碼的時(shí)候發(fā)現(xiàn)的。

  • 在Person中我僅僅只是聲明了@class Car,而沒有引用#import "Car.h",然后在ViewController.m中便可以對(duì)其進(jìn)行: [person setValue:[NSNumber numberWithFloat:price] forKeyPath:@"car.price"];這樣子的賦值。所以說明KVC會(huì)去自動(dòng)查找Car類進(jìn)行賦值。
  • 在對(duì)person.car進(jìn)行賦值的時(shí)候,必須保證car變量的存在,也就是說,必須生成一個(gè)Car對(duì)象賦值給person.car.否則會(huì)拋出野指針異常錯(cuò)誤。
  • 還有就是setValue:forKey:和setValue: forKeyPath:這兩個(gè)方法,可以查看NSObject中的聲明:- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;你會(huì)發(fā)現(xiàn)value的值必須是id,也就是說不能傳基本數(shù)據(jù)類型,必須是指針類型的變量。
KVC和對(duì)象的setter、getter方法的區(qū)別

一般情況下,KVC和setter、getter應(yīng)該說都能達(dá)到對(duì)對(duì)象屬性的賦值,并且KVC操作也是去調(diào)用的setter方法和getter方法(針對(duì)一些已經(jīng)在.h中聲明的屬性而言)。但是對(duì)于一些私有屬性,那么這個(gè)時(shí)候setter、getter方法就沒有用了,這個(gè)時(shí)候KVC卻能發(fā)揮重要優(yōu)勢(shì)。
例如:在Person.m中
#import "Person.h"
@implementation Person
{
NSInteger _height;
}
@end
此時(shí)你會(huì)發(fā)現(xiàn)setter、getter已經(jīng)無能為力了,但是KVC去可以實(shí)現(xiàn)賦值、取值

[p setValue:@170 forKey:@"height"];
key和keyPath的區(qū)別

keyPath方法是集成了key的所有功能,也就是說對(duì)一個(gè)對(duì)象的一般屬性進(jìn)行賦值、取值,兩個(gè)方法是通用的,都可以實(shí)現(xiàn)。但是對(duì)對(duì)象中的對(duì)象進(jìn)的屬性行賦值,只有keyPath能夠?qū)崿F(xiàn)。

setValuesForKeysWithDictionary:的巧妙使用(字典轉(zhuǎn)模型)
-(instancetype)initWithDict:(NSDictionary *)dict{
         if (self = [super init]) {
               [self setValuesForKeysWithDictionary:dict]; 
          } 
         return self;
}
注意點(diǎn):
  • 字典轉(zhuǎn)模型的時(shí)候,字典中的某一個(gè)key一定要在模型中有對(duì)應(yīng)的屬性
  • 如果一個(gè)模型中包含了另外的模型對(duì)象,是不能直接轉(zhuǎn)化成功的。
  • 通過kvc轉(zhuǎn)化模型中的模型,也是不能直接轉(zhuǎn)化成功的。
KVO的用法

KVO也就是key-value-observing(即鍵值觀察),利用一個(gè)key來找到某個(gè)屬性并監(jiān)聽其值得改變。用法如下:

  • 添加觀察者
  • 在觀察者中實(shí)現(xiàn)監(jiān)聽方法,observeValueForKeyPath: ofObject: change: context:(通過查閱文檔可以知道,絕大多數(shù)對(duì)象都有這個(gè)方法,因?yàn)檫@個(gè)方法屬于NSObject)
  • 移除觀察者
//讓對(duì)象b監(jiān)聽對(duì)象a的name屬性
//options屬性可以選擇是哪個(gè)
 /* NSKeyValueObservingOptionNew =0x01, 新值 
  * NSKeyValueObservingOptionOld =0x02, 舊值 
  */ 
[a addObserver:b forKeyPath:@"name"options:kNilOptionscontext:nil]; 
a.name = @"zzz";
#pragma mark - 實(shí)現(xiàn)KVO回調(diào)方法
/* * 當(dāng)對(duì)象的屬性發(fā)生改變會(huì)調(diào)用該方法
    * @param keyPath 監(jiān)聽的屬性 
    * @param object 監(jiān)聽的對(duì)象 
    * @param change 新值和舊值 
    * @param context 額外的數(shù)據(jù) 
*/
- (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,關(guān)于isa指針,會(huì)在隨后的簡(jiǎn)述中介紹)

當(dāng)一個(gè)類的屬性被觀察的時(shí)候,系統(tǒng)會(huì)通過runtime動(dòng)態(tài)的創(chuàng)建一個(gè)該類的派生類,并且會(huì)在這個(gè)類中重寫基類被觀察的屬性的setter方法,而且系統(tǒng)將這個(gè)類的isa指針指向了派生類,從而實(shí)現(xiàn)了給監(jiān)聽的屬性賦值時(shí)調(diào)用的是派生類的setter方法。重寫的setter方法會(huì)在調(diào)用原setter方法前后,通知觀察對(duì)象值得改變。
??具體實(shí)現(xiàn)圖如下,這里我拿的是iOS程序猿的圖,借用一下應(yīng)該沒關(guān)系吧?


今天僅僅是KVO和KVC的簡(jiǎn)單的用法的介紹,隨后會(huì)更加深層次的進(jìn)行介紹,敬請(qǐng)期待.....、

歡迎關(guān)注我的個(gè)人微信公眾號(hào),免費(fèi)送計(jì)算機(jī)各種最新視頻資源!你想象不到的精彩!


0.jpg
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容