本文共 4133 字,大约阅读时间需要 13 分钟。
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类,用于存放账号和密码
#importNS_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*)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"]; }
效果图:
再次修改账号密码转载地址:http://jwkti.baihongyu.com/