iOS KVO用法(附修改账号密码demo)

KVO简介

KVO全称KeyValue Observing,是苹果提供的一套事件通知机制。
作用:允许对象监听另一个对象特定属性的改变,并在改变时接收到事件。
注意:KVO只对属性发生作用,一般继承自NSObject的对象都默认支持KVO。

使用步骤

  • 注册观察者
    使用方法:addObserver:forKeyPath:options:context:
    参数含义:
    1.observer:观察者,监听属性变化的对象。 该对象必须实现 observeValueForKeyPath:ofObject:change:context: 方法。
    2. keyPath:要观察的属性名称。要和属性声明的名称一致。
    3. options:对KVO机制进行配置,修改KVO通知的时机以及通知的内容
    4. context: 传入任意类型的对象,在"接收消息回调"的代码中可以接收到这个对象,是KVO中的一种传值方式。
    options参数:
    enum {
    NSKeyValueObservingOptionNew = 0x01,
    NSKeyValueObservingOptionOld = 0x02,
    NSKeyValueObservingOptionInitial = 0x04,
    NSKeyValueObservingOptionPrior = 0x08
    };
    typedef NSUInteger NSKeyValueObservingOptions;
    默认只接受新值
    NSKeyValueObservingOptionNew:接收方法中使用change参数传入变化后的新值,键为:NSKeyValueChangeNewKey;
    NSKeyValueObservingOptionOld:接收方法中使用change参数传入变化前的旧值,键为:NSKeyValueChangeOldKey;
    NSKeyValueObservingOptionInitial:注册之后立刻调用接收方法,如果配置了NSKeyValueObservingOptionNew,change参数内容会包含新值,键为:NSKeyValueChangeNewKey;
    NSKeyValueObservingOptionPrior:如果加入这个参数,接收方法会在变化前后分别调用一次,共两次,变化前的通知change参数包含notificationIsPrior = 1。

  • 接收通知
    使用方法:observeValueForKeyPath:ofObject:change:context:

  • 取消注册
    使用方法:removeObserver:forKeyPath:context

例子

首先创建一个继承自NSObject的massage类,用于存放账号和密码

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface massage : NSObject

@property (nonatomic, strong) NSString *strNameWord;
@property (nonatomic, strong) NSString *strPassWord;

@end

然后在ViewController.m里创建两个TextField和一个用于确认修改账号的button

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    _aMassage = [[massage alloc] init];
    _aMassage.strNameWord = @"123";
    _aMassage.strPassWord = @"456";
    //给账号和密码注册监听
    [_aMassage addObserver:self forKeyPath:@"strNameWord" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    [_aMassage addObserver:self forKeyPath:@"strPassWord" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    
    _nameTextField = [[UITextField alloc] init];
    [self.view addSubview:_nameTextField];
    _nameTextField.frame = CGRectMake(50, 150, 300, 50);
    _nameTextField.layer.masksToBounds = YES;
    _nameTextField.layer.borderWidth = 2;
    _nameTextField.layer.cornerRadius = 5;
    _nameTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _nameTextField.delegate = self;
    
    _passTextField = [[UITextField alloc] init];
    [self.view addSubview:_passTextField];
    _passTextField.frame = CGRectMake(50, 230, 300, 50);
    _passTextField.layer.masksToBounds = YES;
    _passTextField.layer.borderWidth = 2;
    _passTextField.layer.cornerRadius = 5;
    _passTextField.layer.borderColor = [UIColor blackColor].CGColor;
    _passTextField.delegate = self;
    
     
    UIButton *reviseBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [self.view addSubview:reviseBtn];
    [reviseBtn addTarget:self action:@selector(pressBtn) forControlEvents:UIControlEventTouchUpInside];
    [reviseBtn setTitle:@"revise" forState:UIControlStateNormal];
    [reviseBtn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    reviseBtn.frame = CGRectMake(150, 320, 100, 50);
    
}

在button点击事件里触发监听

- (void)pressBtn {
    
    NSLog(@"revise!");
    //触发监听
    //第一种方法
    NSDictionary *newMassageDictionary = [NSDictionary dictionaryWithObjectsAndKeys:_nameTextField.text,@"strNameWord",_passTextField.text,@"strPassWord", nil];
    [_aMassage setValuesForKeysWithDictionary:newMassageDictionary];
    //第二种方法
//    [_aMassage setValue:@"000" forKey:@"strPassWord"];
    
}

当KVO事件到来时会调用这个方法,如果没有实现会导致Crash

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    if ([keyPath isEqualToString:@"strNameWord"]) {
        NSLog(@"old nameWord: %@", [change objectForKey:@"old"]);
        NSLog(@"new nameWord: %@", [change objectForKey:@"new"]);
    }
    
    if ([keyPath isEqualToString:@"strPassWord"]) {
        NSLog(@"old PassWord: %@", [change objectForKey:@"old"]);
        NSLog(@"new PassWord: %@", [change objectForKey:@"new"]);
    }
    
}

最后移除监听

- (void)dealloc {
    
    [_aMassage removeObserver:self forKeyPath:@"strPassWord"];
    
}

效果图:
在这里插入图片描述
在这里插入图片描述
再次修改账号密码
在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值