iOS —— 初识KVO

iOS —— 初始KVO

  • KVO的基础
    • 1. KVO概念
    • 2. KVO使用步骤
      • 注册KVO监听
      • 实现KVO监听
      • 销毁KVO监听
    • 3. KVO基本用法
    • 4. KVO传值
    • 禁止KVO的方法
  • 注意事项:

KVO的基础

1. KVO概念

KVO是一种开发模式,它的全称是Key-Value Observing (观察者模式) 是苹果Fundation框架下提供的一种开发机制,使用KVO,可以方便地对指定对象的某个属性进行观察,当属性发生变化时,进行通知,告诉开发者属性旧值和新值对应的内容。

2. KVO使用步骤

注册KVO监听

通过[addObserver:forKeyPath:options:context:]方法注册KVO,这样可以接收到keyPath属性的变化事件;

  • observer:观察者,监听属性变化的对象。该对象必须实现observeValueForKeyPath:ofObject:change:context: 方法。
  • keyPath:要观察的属性名称。要和属性声明的名称一致。
  • options:回调方法中收到被观察者的属性的旧值或新值等,对KVO机制进行配置,修改KVO通知的时机以及通知的内容。
  • context:传入任意类型的对象,在"接收消息回调"的代码中可以接收到这个对象,是KVO中的一种传值方式。

实现KVO监听

通过方法[observeValueForKeyPath:ofObject:change:context:]实现KVO的监听;

  • keyPath:被观察对象的属性。
  • object:被观察的对象。
  • change:字典,存放相关的值,根据options传入的枚举来返回新值旧值。
  • context:注册观察者的时候,context传递过来的值。

销毁KVO监听

在不需要监听的时候,通过方法**[removeObserver:forKeyPath:],**移除监听。

3. KVO基本用法

我们可以通过对button的背景颜色进行监听,当背景颜色改变的时候,分别打印出背景颜色的前后变化的数值。

self.button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.button.frame = CGRectMake(150, 150, 100, 100);
    self.button.backgroundColor = UIColor.yellowColor;
    [self.view addSubview:self.button];
    
    [self.button addTarget:self action:@selector(press:) forControlEvents:UIControlEventTouchUpInside];
    
    [self.button addObserver:self forKeyPath:@"backgroundColor" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
- (void)press {
    //改变被监听对象的值
    [self.kvoButton setValue:[UIColor colorWithRed:arc4random() % 255 / 255.0 green:arc4random() % 255 / 255.0 blue:arc4random() % 250 / 250.0 alpha:1] forKey:@"backgroundColor"];
}

//当属性变化时会激发该监听方法
- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    //打印监听结果
    if ([keyPath isEqual:@"backgroundColor"]) {
        NSLog(@"old value is: %@", [change objectForKey:@"old"]);
        NSLog(@"new value is: %@", [change objectForKey:@"new"]);
    }
}

我们点击一次button:
在这里插入图片描述

4. KVO传值

KVO传值也很简单,可以理解为我们对第二个viewController的某一个属性做一个监听,当我们跳转到第一个viewController的时候就可以监听到值的改变。KVO传值也很简单,可以理解为我们对第二个viewController的某一个属性做一个监听,当我们跳转到第一个viewController的时候就可以监听到值的改变。

//第一个视图部分
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    
    self.label = [[UILabel alloc] init];
    self.label.text = @"还没传值";
    self.label.frame = CGRectMake(150, 300, 100, 25);
    
    self.button = [UIButton buttonWithType:UIButtonTypeCustom];
    self.button.frame = CGRectMake(150, 150, 100, 100);
    self.button.backgroundColor = UIColor.blueColor;
    [self.button addTarget:self action:@selector(press) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:self.button];
    [self.view addSubview:self.label];
    
}

- (void) press {
    secondViewController* second = [[secondViewController alloc] init];
    second.modalPresentationStyle = UIModalPresentationFullScreen;
    [second addObserver:self forKeyPath:@"context" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    
    [self presentViewController:second animated:YES completion:nil];
}

- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if ([keyPath isEqual:@"context"]) {
        id value = [change objectForKey:@"new"];
        self.label.text = value;
        
    }
}
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.view.backgroundColor = [UIColor orangeColor];
    self.backButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    self.backButton.frame = CGRectMake(100, 100, 100, 100);
    self.backButton.backgroundColor = [UIColor blueColor];
    [self.backButton addTarget:self action:@selector(pressBack) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:self.backButton];
    
    self.textField = [[UITextField alloc] initWithFrame:CGRectMake(100, 250, 200, 50)];
    self.textField.keyboardType = UIKeyboardTypeDefault;
    self.textField.borderStyle = UITextBorderStyleRoundedRect;
    [self.view addSubview:self.textField];
    
}

- (void) pressBack {
    self.context = self.textField.text;
    [self dismissViewControllerAnimated:YES completion:nil];
}

运行的结果如下:
刚进入的页面:
在这里插入图片描述
然后通过按钮进入到下一个界面。
在textFiled中写入文本,
在这里插入图片描述
然后返回到前一个界面,之后会发现上一个界面中的值传到了这个界面中,如下图:
在这里插入图片描述

禁止KVO的方法

//返回NO禁止KVO
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
    if ([key isEqualToString:@"content"]) {
        return NO;
    } else {
        return [super automaticallyNotifiesObserversForKey:key];
    }
}

注意事项:

  • 调用[removeObserver:forKeyPath:]需要在观察者消失之前,否则会导致Crash。
  • 在调用addObserver方法后,KVO并不会对观察者进行强引用,所以需要注意观察者的生命周期,否则会导致观察者被释放带来的Crash。
  • 观察者需要实现observeValueForKeyPath:ofObject:change:context:方法,当KVO事件到来时会调用这个方法,如果没有实现会导致Crash。
  • KVO的addObserver和removeObserver需要是成对的,如果重复remove则会导致NSRangeException类型的Crash,如果忘记remove则会在观察者释放后再次接收到KVO回调时Crash。
  • 在调用KVO时需要传入一个keyPath,由于keyPath是字符串的形式,所以其对应的属性发生改变后,字符串没有改变容易导致Crash。我们可以利用系统的反射机制将keyPath反射出来,这样编译器可以在@selector()中进行合法性检查。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/496499.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

蓝桥备赛——DFS

废话不多说&#xff0c;先上题 对应代码如下&#xff1a; def dfs(x,y):global numfor i in range(0,4):dir[(-1,0),(0,-1),(1,0),(0,1)]nx,nyxdir[i][0] ,ydir[i][1]if nx<0 or nx>hx or ny <0 or ny>wy: continueif mp[nx][ny]*:num1print("%d:%s->%d%…

ROS 2边学边练(3)-- 何为节点(nodes)

在接触节点这个概念之前&#xff0c;我们先来看看下面这张动态图&#xff0c;更方便我们理解一些概念和交互过程。 &#xff08;相信大家的英文基础哈&#xff09; 概念 如上图所示&#xff0c;这里面其实涉及到了三个概念&#xff08;功能&#xff09;&#xff0c;分别是节点…

深入解析Spring MVC: 原理、流程【面试版】

什么是SpringMV? 1.是一个基于MVC的web框架&#xff1b; 2.是spring的一个模块&#xff0c;是spring的子容器&#xff0c;子容器可以拿父容器的东西&#xff0c;但是反过来不可&#xff1b; 2.SpringMVC的前端控制器是DispatcherServlet&#xff0c;用于分发请求。使开发变…

009——服务器开发环境搭建及开发方法(上)

目录 一、环境搭建 1.1网络环境 1.2 文件传输环境搭建 1.2.1 nfs环境 1.2.2 tftp环境 1.3 源码环境搭建 1.4 代码托管 1.5 配置交叉编译工具链 二、 开发方式 2.1 内核、设备树、驱动 make mrproper make 100ask_imx6ull_mini_defconfig​编辑 make zImage -j4 m…

Kubernetes Gateway API 介绍

Kubernetes Gateway API 诞生背景 在 kubernetes 中&#xff0c;流量的治理主要分为两个部分&#xff1a; 南北向流量东西向流量 南北向流量&#xff08;NORTH-SOUTH traffic&#xff09; 在计算机网络中&#xff0c;南北向流量通常指数据流量从一个**内部网络&#xff08;…

结构数列演化中的分枝

假设一个6*6的平面&#xff0c;这个平面的行和列可以自由的变换。 已知一个4点的结构数列顺序为 9 1 10 6 16 14 5 15 8 12 11 13 7 2 4 3 让这个数列按照4-5-4的方式演化 得到顺序为 1 9 1 10 6 16 14 5 15 8 12 11 13 7 2 4 3 2 16 6 9…

无需插件就能实现异构数据库的互联互通?(powershell妙用)

前两天在DBA群里有大佬分享了利用Oracle Database Gateway&#xff08;透明网关&#xff09;实现sqlserver和oracle 的数据交互&#xff0c;这里让我想到前些年写的一些powershell脚本用来做sqlserver和oracle的数据交互&#xff0c;powershell是windows自带的一个脚本工具&…

红队笔记8-CTF5打靶流程-CMS漏洞-多用户信息泄露(vulnhub)

目录 开头: 1.主机发现和端口扫描&#xff1a; 2.80端口-NanoCMS哈希密码信息泄露-后台getshell 3.提权-用户过多信息泄露 4.总结&#xff1a; 开头: 学习的视频是哔哩哔哩红队笔记&#xff1a; 「红队笔记」靶机精讲&#xff1a;LAMPSecurityCTF5 - 标准攻击链&#xff…

图论-最短路

一、不存在负权边-dijkstra算法 dijkstra算法适用于这样一类问题&#xff1a; 从起点 start 到所有其他节点的最短路径。 其实求解最短路径最暴力的方法就是使用bfs广搜一下&#xff0c;但是要一次求得所有点的最短距离我们不可能循环n次&#xff0c;这样复杂度太高&#xf…

vue.js——学习计划表

1&#xff09;准备工作 ①打开D:\vue\chapter02\ learning_schedule 目录&#xff0c;找到 index.html 文件。 在文件中引 入BootStrap 样式文件&#xff0c;具体代码如下 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8&qu…

vivado 手动布线

手动路由 手动路由允许您为网络选择特定的路由资源。这给了你对信号将要采用的路由路径的完全控制。手动路由不调用route_design。路线在路线数据库中直接更新。当您想精确控制网络的延迟时&#xff0c;可能需要使用手动路由。对于例如&#xff0c;假设有一个源同步接口&#…

面试题--3.18

1. http与https的区别&#xff0c;以及https的认证过程及加密算法 &#xff1f; 区别&#xff1a; https协议需要到CA申请证书&#xff0c;一般免费证书较少&#xff0c;因而需要一定费用。 http是超文本传输协议&#xff0c;信息是明文传输&#xff0c;https则是具有安全性…

大型语言模型:技术回顾

公众号&#xff1a;Halo 咯咯&#xff0c;欢迎关注~ 简介 很难说自然语言处理&#xff08;NLP&#xff09;的旅程是什么时候开始的。根据维基百科的文章《自然语言处理的历史》[1]&#xff0c;它可能始于 17 世纪&#xff0c;当时莱布尼茨和笛卡尔试图理解不同语言中单词之间的…

让人担心的软件生态

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 其实很久之前shigen就想写这样的一篇文章&#xff0c;思考现在的软件生态和我们…

c语言数据结构(9)——插入排序、希尔排序

欢迎来到博主的专栏——C语言数据结构 博主ID&#xff1a;代码小豪 文章目录 排序插入排序希尔排序 排序 现在有N个数据的序列&#xff0c;其对应的序列号为[r1 ,r2 ……rn];将该序列对应的数据[k1 ,k2 ……kn]排成满足递减或递减的序列的操作称为排序 插入排序 玩过斗地主…

tomcat配置静态资源后无法正常访问

目录 一、场景二、配置三、访问异常四、排查五、原因六、解决 一、场景 1、将前端文件存在到指定目录 2、在tomcat配置静态资源 3、配置后无法正常访问到前端文件 二、配置 1、tomcat配置 2、静态资源 三、访问异常 四、排查 可以ping通&#xff0c;但是访问不了3080端口 …

探究WordPress受欢迎的原因及其org和com的区别

在当今互联网时代&#xff0c;WordPress已经成为了建立网站的首选工具之一&#xff0c;其受欢迎程度远远超出了其他竞争对手。那么&#xff0c;为什么WordPress如此受欢迎呢&#xff1f;让我们一起探究一下。 首先&#xff0c;WordPress是一个开源项目&#xff0c;这意味着任何…

【UEditorPlus】后端配置项没有正常加载,上传插件不能正常使用

解决办法&#xff1a; 1、找到UEditorPlus的根目录&#xff0c;修改 ueditor.all.js 文件 搜索&#xff1a;isJsonp utils.isCrossDomainUrl(configUrl); 更改为&#xff1a;isJsonp false; 2、重新运行前端即可正常使用 如果出现依旧不行&#xff0c;请关闭服务&#xff…

如何选择适合自己的办公空间

说到办公地点的选择&#xff0c;其实就跟挑衣服似的&#xff0c;得看场合、看需求&#xff0c;还得看个人喜好。有的人喜欢自由自在&#xff0c;有的人则需要稳定和私密。所以&#xff0c;咱们来看看哪些朋友更适合哪种办公环境。 适合共享办公室的&#xff1a; 刚起步的小公司…

教师的晋升通道:走向专业成长的阶梯

教师是一项需要不断学习、不断进步的职业。随着教育改革的不断深入&#xff0c;教师的晋升通道也越来越受到关注。本文将从教师的晋升通道、晋升标准和未来发展方向等方面进行探讨&#xff0c;旨在帮助广大教师了解自己的职业成长路径&#xff0c;促进个人发展。 一、教师的晋升…
最新文章