美文网首页
iOS中KVC及KVO的简单理解

iOS中KVC及KVO的简单理解

作者: f1e583c455bf | 来源:发表于2017-05-02 10:41 被阅读0次

一、KVC及KVO的介绍

KVC:即Key-Value-Coding,用于键值编码。
KVO:即Key-Value-Observing,用于键值监听。

KVC:

  • 只针对类属性,设置键值对
  • 设置 setValue: forKey: ,即forKey只能为类属性
  • 取值 valueForKey

一个非正式的Protocol,提供一种机制来间接访问对象的属性。而不是通过调用Setter、Getter方法访问。
无论是Swift还是Objective-C,KVC的定义都是对NSObject的扩展来实现的(Objective-c中有个显式的NSKeyValueCoding类别名,而Swift没有,也不需要)所以对于所有继承了NSObject在类型,都能使用KVC(一些纯Swift类和结构体是不支持KVC的),下面是KVC最为重要的四个方法

- (nullable id)valueForKey:(NSString *)key;                          //直接通过Key来取值
- (void)setValue:(nullable id)value forKey:(NSString *)key;          //通过Key来设值
- (nullable id)valueForKeyPath:(NSString *)keyPath;                  //通过KeyPath来取值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;  //通过KeyPath来设值

KVC可以在运行时动态的访问和修改对象的属性,而不是在编译时确定。允许通过Key值访问对象属性,或者给对象赋值。

KVO:
KVO是Objective-C对观察这设计模式的一种实现。(另一种是:通知机制(notification))。
KVO提供一种机制,指定一个被观察对象,当对象某个属性发生改变时,对象会获得通知。当观察某对象A时,KVO机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性keyPath的setter 方法。setter 方法随后负责通知观察对象属性的改变状况。

  • 利用KVC对类属性进行设置
  • 注册observing对象** addObserver:forKeyPath:options:context:**
  • 观察者必须重写方法 observeValueForKeyPath:ofObject:change:context:

KVO是建立在KVC之上的,KVO能够观察一个对象的KVC key-path值的变化。

二、KVC及KVO的使用

<一>、kvc的使用

KVC在内部寻找key的是顺序:

  1. KVC机制,程序优先找set方法,set<key>
  2. 如果没有set方法,** accessInstanceVariablesDirectly 方法如果返回Yes,KVC会执行setValue:forUNdefinedKey:方法,找成员变量_<key>(默认返回YES)如果重写了该方法让其返回NO的话,那么在这一步KVC会执行setValue:forUNdefinedKey:**方法
  3. 如果即没有set<Key>:方法,也没有_<key>成员变量,KVC机制会搜索is<Key>的成员变量,,如果该类即没有set<Key>:方法,也没有<key>和_is<Key>成员变量,KVC机制再会继续搜索<key>和is<Key>的成员变量。再给它们赋值。
  4. 如果都没有,则会执行setValue:forUNdefinedKey:方法
#import "ViewController.h"
@interface ViewController ()
{
    NSString *testNoSetFunc;
}
@property (nonatomic, strong) NSString *testStr;//默认生成成员变量及get、set方法

@end

@implementation ViewController

//accessInstanceVariablesDirectly重写
+ (BOOL)accessInstanceVariablesDirectly{
    //默认返回YES,表示如果没有找到Set<Key>方法的话,会按照_key,_iskey,key,iskey的顺序搜索成员,设置成NO就不这样搜索

    return NO;
}
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *test;//既没有成员变量也没有setter方法

    //fuzhi
    [self setValue:@"测试" forKey:@"test"];
    [self setValue:@"测试" forKey:@"testNoSetFunc"];
    [self setValue:@"测试" forKey:@"testStr"];
    
    //取值
    NSString *getTestNoSetFunc = [self valueForKey:@"testNoSetFunc"];
    NSString *getTest = [self valueForKey:@"test"];
    NSString *getTestStr = [self valueForKey:@"testStr"];

}

-(id)valueForUndefinedKey:(NSString *)key{
    NSLog(@"该key不存在%@",key);
    return nil;
}
//如果Key不存在,且没有KVC无法搜索到任何和Key有关的字段或者属性,则会调用这个方法,默认是抛出异常
-(void)setValue:(id)value forUndefinedKey:(NSString *)key{
    NSLog(@"该key不存在%@",key);
}

@end

如果一个类的成员变量是其他自定义类 可用valueForKeyPath 及
setValue:forKeyPath取值、赋值
valueForKeyPath
[类名 valueForKeyPath:@"类对象.类属性"];
setValue:forKeyPath:
[类名 setValue:@"值" forKeyPath:@"类对象.类属性"];

使用场景

<一>、kvc的使用

KVC是基于运行时的编程,极大的提高了灵活性,简化了代码。
(1)、动态地取值和赋值
(2)、用KVC来访问和修改私有变量
==对于类里的私有属性,Objective-C是无法直接访问的,但是KVC是可以的
(3)、Model和字典转换
(4)、修改一些控件的内部属性

    //1.添加textfield
    UITextField *textField = [[UITextField alloc]init];
    [self.view addSubview:textField];
    textField.frame = CGRectMake(10, 100, self.view.frame.size.width - 20, 30);
    //2.利用KVC修改placeholder的颜色
    textField.placeholder = @"请输入";
    [textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
<二>、kvo的使用

如果赋值没有通过setter方法或者KVC,而是直接修改属性对应的成员变量,例如:仅调用_name = @"newName",这时是不会触发kvo机制,更加不会调用回调方法的。
所以使用KVO机制的前提是遵循 KVO 的属性设置方式来变更属性值。

  1. 注册观察者,实施监听;
  2. 在回调方法中处理属性发生的变化;
  3. 移除观察者
#import "ViewController.h"
@interface ViewController ()
@property (nonatomic, strong) NSString *name;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.name = @"测试";
    //1.注册通知
    [self addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];

}
//2.监听值改变
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:@"name"]&&object == self) {
        //
        self.view.backgroundColor = [UIColor redColor];
        NSLog(@"name的新值%@",[change valueForKey:@"new"]);
        NSLog(@"name的旧值%@",[change valueForKey:@"old"]);

    }
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    self.name = @"更改name的值";
}
//3.移除通知
- (void)dealloc{
    [self removeObserver:self forKeyPath:@"name"];
}
@end

KVO可监听自定义类属性的变化

//testModel.h
#import <Foundation/Foundation.h>

@interface testModel : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *number;

@end

//ViewController.m
#import "ViewController.h"
#import "testModel.h"
@interface ViewController ()
@property (nonatomic, strong) testModel *model;

@end

@implementation ViewController


- (void)viewDidLoad {
    [super viewDidLoad];

    testModel *model = [[testModel alloc]init];
    self.model = model;
    model.name = @"测试";
    //1.注册通知
    [self.model addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];


}
//2.监听值改变
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    if ([keyPath isEqualToString:@"name"]&&object == self.model) {
        //
        self.view.backgroundColor = [UIColor redColor];
        NSLog(@"name的新值%@",[change valueForKey:@"new"]);
        NSLog(@"name的旧值%@",[change valueForKey:@"old"]);

    }
    
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    if (![self.model.name isEqualToString:@"更改name的值"]) {
        self.model.name = @"更改name的值";

    }
}
//3.移除通知
- (void)dealloc{
    [self.model removeObserver:self forKeyPath:@"name"];
}
@end

相关文章

  • 从网上收集的一些关键知识点总结

    iOS 中KVC、KVO、NSNotification、delegate 总结及区别

  • KVC,KVO,消息,代理

    iOS 中KVC、KVO、NSNotification、delegate 总结及区别 1、KVC,即是指 NSKe...

  • iOS中KVC及KVO的简单理解

    一、KVC及KVO的介绍 KVC:即Key-Value-Coding,用于键值编码。KVO:即Key-Value-...

  • KVC

    iOS 如何使用KVC iOS开发UI篇—Kvc简单介绍 iOS开发系列--Objective-C之KVC、KVO

  • day02

    1) iOS 中KVC、KVO总结及区别 1、KVC,即是指 NSKeyValueCoding,一个非正式的Pro...

  • iOS日记15-KVC

    1.iOS开发技巧系列---详解KVC 2.漫谈 KVC 与 KVO 3.KVC/KVO原理详解及编程指南 关键点...

  • 说一下KVC和KVO

    本篇采用简单的例子,来介绍 iOS 中的 KVC 和 KVO 的用法和实现原理。 一、KVC 1. KVC是什么 ...

  • KVC

    KVC原理剖析 - CocoaChina_让移动开发更简单 iOS开发底层细究:KVC和KVO底层原理 | iOS...

  • KVC,KVO

    KVC , KVO KVC和KVO的区别及应用 KVC/KVO原理 1. KVC键值编码 KVC,即是指NSKey...

  • KVO与KVC简单理解

    KVO与KVC简单理解 ///////////////////////////////////////我是该死的分...

网友评论

      本文标题:iOS中KVC及KVO的简单理解

      本文链接:https://www.haomeiwen.com/subject/rebvzttx.html