iOS——KVO与通知传值

KVO

KVO是什么

KVO:Key-Value Observing,是Foundation框架提供的一种机制,使用KVO,可以方便地对指定对象的某个属性进行观察,当属性发生变化时,进行通知。

KVO的用法

一般使用KVO时,总共分为三个步骤:

  1. 设置监听:
//注册观察者 observer:观察者对象; KeyPath:要监测的键路径;options:需要监测的选项;context:上下文用来区分消息;
_kvoTest = [[KVOTestModel alloc] init];
// 给属性nameStr设置监听,类型不同,回调值不同,这里监听的是新值(NSKeyValueObservingOptionNew),还可以监听其他变化
[_kvoTest addObserver:self forKeyPath:@"nameStr" options:NSKeyValueObservingOptionNew context:nil];
  1. 实现监听回调方法:
// 监听的属性通过kvc发生变化时,执行下面方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    
    // 这里我们只判断了keyPath,如果存在多个kvo,为防止重名,可判断object是否为我们监听的实例:_kvoTest
    if ([keyPath isEqualToString:@"nameStr"]) {
        // 我们直接打印新值
        NSLog(@"change: %@",[change objectForKey:NSKeyValueChangeNewKey]);
    }
}

  1. 在使用完KVO之后,一定要移除观察者调用removeObserver:forKeyPath:方法将KVO移除。需要注意的是,调用removeObserver需要在观察者消失之前,否则会导致Crash。

实现原理

KVO是根据iOS runtime实现的,当监听某个对象(_kvoTest)的某个属性时,KVO会创建这个对象的子类,并重写我们监听的属性(keyPath)的set方法,具体实现可能是下面这个样子:

- (void)setNameStr:(NSString *)nameStr {
    [self willChangeValueForKey:@"nameStr"];
    [super setValue:nameStr forKey:@"nameStr"];
    [self didChangeValueForKey:@"nameStr"];
}


通知传值

首先通知传值也是逆向传值的一种,我们必须要 知道通知传值是谁要监听值的变化,谁就注册通知 特别要注意,通知的接受者必须存在这一条件 。

通知传值方法

  1. 注册通知
  2. 通知中心发送通知消息,其中name(通知名)前后要保持一致性
  3. 实现通知内部的方法,并实现传值
  4. 消息发送完之后,要移除通知

通知传值使用

首先我们先在第二个页面(SecondViewController.m)用懒加载创建UITextField和UIButton。

-(UITextField *)textField {

    if (!_textField) {

        _textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 50)];
        _textField.borderStyle = UITextBorderStyleRoundedRect;
        _textField.backgroundColor = [UIColor whiteColor];

    }
    return _textField;
}


-(UIButton *)Button {

    if (!_button) {

        _button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _button.frame = CGRectMake(20, 200, self.view.bounds.size.width-40,40);

        _button.backgroundColor = [UIColor blueColor];
        _button.tintColor = [UIColor whiteColor];
        _button.titleLabel.font = [UIFont systemFontOfSize:25.0];

        [_button setTitle:@"Back" forState:UIControlStateNormal];
        [_button addTarget:self action:@selector(backBtn:) forControlEvents:UIControlEventTouchUpInside];

    }
    return _button;

}


- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor cyanColor];

    [self.view addSubview:self.textField];
    [self.view addSubview:self.button];


}

接着我们完成按钮对应的事件:

-(void)pressback:(UIButton *)sender{

//    发送通知
    [[NSNotificationCenter defaultCenter]postNotificationName:@"ChangeValue" object:nil userInfo:@{@"Value":_textField.text}];
    NSLog(@"%@",self.textField.text);
    [self dismissViewControllerAnimated:YES completion:nil];

}

在ViewController.m中:


#import "ViewController.h"
#import "SecondViewController.h"

@interface ViewController ()
@property (nonatomic,strong) UITextField *textField;
@property (nonatomic,strong) UIButton *nextBtn;


@end


@implementation ViewController
-(UITextField *)textField{

    if (!_textField) {
        _textField = [[UITextField alloc]initWithFrame:CGRectMake(0, 100, self.view.bounds.size.width, 50)];
        _textField.borderStyle = UITextBorderStyleRoundedRect;
        _textField.backgroundColor = [UIColor whiteColor];

    }
    return _textField;
}

-(UIButton *)nextBtn{

    if (!_nextBtn) {

        _nextBtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        _nextBtn.frame = CGRectMake(20, 200, self.view.bounds.size.width - 40, 44);

        _nextBtn.backgroundColor = [UIColor blueColor];
        _nextBtn.titleLabel.font = [UIFont systemFontOfSize:25.0];
        _nextBtn.tintColor = [UIColor whiteColor];

        [_nextBtn setTitle:@"Next" forState:UIControlStateNormal];
        [_nextBtn addTarget:self action:@selector(nextBtn:) forControlEvents:UIControlEventTouchUpInside];

    }
    return _nextBtn;
}

- (void)viewDidLoad {
    [super viewDidLoad];

    /*
     通知传值(逆向传值 --> 第二个界面传值到第一个界面)
     1 注册通知
     2 通知中心发送一条消息通知,其中name前后一定要一样
     3 实现通知中心内部的方法,并实现传值
     4 消息发送完,要移除掉。(页面将要消失的时候)
     */
    self.navigationItem.title = @"通知传值";
    self.view.backgroundColor = [UIColor orangeColor];

    [self.view addSubview:self.textField];
    [self.view addSubview:self.nextBtn];


//    注册监听者
    /*
      addObserver 注册监听者,一般都是控制器本身去监听一个通知
      selector 当监听到通知的时候执行的方法
      name 通知的名字,要和发送的通知的对象的名字一致
     */
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(ChangeTextFText:) name:@"ChangeValue" object:nil];

}
-(void)ChangeTextFText:(NSNotification *)notification{

    NSDictionary *dict = notification.userInfo;
    NSLog(@"dict = %@",dict);
    _textField.text = dict[@"Value"];

}

-(void)nextBtn:(UIButton *)sender{
    SecondViewController *secondViewController = [[SecondViewController alloc]init];
    secondViewController.modalPresentationStyle = UIModalPresentationFullScreen;
    [self presentViewController:secondViewController animated:YES completion:nil];

}
//移除通知
-(void)dealloc{
    [[NSNotificationCenter defaultCenter]removeObserver:self];
}

@end

核心方法代码:

//创建通知 
    NSNotification * notification = [NSNotification notificationWithName:@"ChangeValue" object:nil userInfo:nil];
    //通过通知中心发送通知
    [[NSNotificationCenter defaultCenter]postNotification:notification];

//注册(接收通知)
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi) name:@"ChangeValue" object:nil];

//用完以后移除通知
[[NSNotificationCenter defaultCenter]removeObserver:self name:@"ChangeValue" object:nil];

iOS——KVO与通知传值_第1张图片

iOS——KVO与通知传值_第2张图片

你可能感兴趣的:(ios,javascript)