【iOS开发】——KVO传值

KVO简介

KVO(Key-Value-Observing,键值观察),即观察关键字的值的变化。首先在子页面中声明一个待观察的属性,在返回主页面之前修改该属性的值。在主页面中提前分配并初始化子页面,并且注册对子页面中对应属性的观察者。在从子页面返回上主之前,通过修改观察者属性的值,在主页面中就能自动检测到这个改变,从而读取子页面的数据。KVO只对属性发生作用

KVO传值适用的场景

已经通过push的方式进入到子页面,在从子页面返回主页面的时候(子页面会释放掉内存),需要在主页面中使用子页面中的数据,这是就可以利用代理反向传值。

传递方向

从后向前的传值

使用步骤

1.步骤一:在界面一注册观察者
使用的方法:addObserver:forKeyPath:options:context:
参数含义:P1:观察者,该对象必须实现 该对象必须实现 observeValueForKeyPath:ofObject:change:context: 方法。
P2:要观察的属性。
P3:选择监听返回的值的类型。
enum {
NSKeyValueObservingOptionNew 接收方法中使用change参数传入变化后的新值
NSKeyValueObservingOptionOld 接收方法中使用change参数传入变化前的旧值
NSKeyValueObservingOptionInitial change参数内容会包含新值
NSKeyValueObservingOptionPrior 如果加入这个参数,接收方法会在变化前后分别调用一次,共两次,变化前的通知change参数
};
P4:传入任意类型的对象,在"接收消息回调"的代码中可以接收到这个对象,是KVO中的一种传值方式。(注意:现在目前好像只可以使用nil,具体怎么用希望路过的大佬可以帮我回答一下

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

删除KVO:
使用方法:removeObserver:forKeyPath:context

代码:

//FirstViewController.m
#import "FirstViewController.h"
#import "SecondViewController.h"
@interface FirstViewController ()

@property (strong, nonatomic) UITextField *textField;
@property (strong, nonatomic) UIButton *button;

//在主页面注册观察者,实现KVO的回调方法,并在主页面销毁时移除观察者
@property (strong, nonatomic) SecondViewController *subVC;

@end

@implementation FirstViewController

- (void)viewDidLoad {
    
    
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    self.title = @"主界面";
    
    _textField = [[UITextField alloc] init];
    _textField.textColor = [UIColor whiteColor];
    _textField.textAlignment = NSTextAlignmentCenter;
    _textField.backgroundColor = [UIColor blackColor];
    _textField.frame = CGRectMake(100, 100, 200, 60);
    [self.view addSubview:_textField];
    
    _button = [UIButton buttonWithType:UIButtonTypeCustom];
    [_button setTitle:@"跳转到子界面" forState:UIControlStateNormal];
    [_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
    _button.frame = CGRectMake(100, 300, 200, 60);
    [self.view addSubview:_button];
}
 - (void) btnClicked:(UIButton *)btn {
    
    
     if (!_subVC) {
    
    
         _subVC = [[SecondViewController alloc] init];
         //注册观察者
         [_subVC addObserver:self forKeyPath:@"content" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
     }
     [self.navigationController pushViewController:_subVC animated:YES];

//     SecondViewController* second = [[SecondViewController alloc] init];
//     [self.navigationController pushViewController:second animated:YES];
 }
// KVO的回调,当观察者中的数据有变化时会回调该方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    
    if ([keyPath isEqualToString:@"content"]){
    
    
        self.textField.text = self.subVC.content;
        NSLog(@"old text:%@   new text:%@", [change objectForKey:NSKeyValueChangeOldKey], [change objectForKey:NSKeyValueChangeNewKey]);
        //也可以这么写
//        NSLog(@"old text:%@   new text:%@", [change objectForKey:@"old"], [change objectForKey:@"new"]);
    }
}


- (void)dealloc {
    
    
    //移除观察者
    [self.subVC removeObserver:self forKeyPath:@"content"];
}
@end

//SecondViewController.m
#import "SecondViewController.h"

@interface SecondViewController ()

@property (strong, nonatomic) UITextField *textField;
@property (strong, nonatomic) UIButton *button;
@property (strong, nonatomic) NSString* content;
@end

@implementation SecondViewController

- (void)viewDidLoad {
    
    
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.view.backgroundColor = [UIColor whiteColor];
    self.title = @"子界面";
    
    _textField = [[UITextField alloc] init];
    _textField.textColor = [UIColor whiteColor];
    _textField.textAlignment = NSTextAlignmentCenter;
    _textField.backgroundColor = [UIColor blackColor];
    _textField.frame = CGRectMake(100, 100, 200, 60);
    [self.view addSubview:_textField];
    
    _button = [UIButton buttonWithType:UIButtonTypeCustom];
    [_button setTitle:@"跳转到主界面" forState:UIControlStateNormal];
    [_button setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
    [_button addTarget:self action:@selector(btnClicked:) forControlEvents:UIControlEventTouchUpInside];
    _button.frame = CGRectMake(100, 300, 200, 60);
    [self.view addSubview:_button];
}
//子页面在返回主页面时修改对应属性的内容,则会回调主页面的回调方法   
- (void) btnClicked:(UIButton *)btn {
    
    
    self.content = _textField.text;//修改属性的内容
    [self.navigationController popViewControllerAnimated:YES];
   
}
@end

效果图:
请添加图片描述

请添加图片描述

请添加图片描述
请添加图片描述

参考文章:1.iOS KVO用法(附修改账号密码demo)
2.iOS学习——页面的传值方式iOS----KVC和KVO 详解

猜你喜欢

转载自blog.csdn.net/weixin_50990189/article/details/119353876