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()中进行合法性检查。
相关文章:
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框架…...
什么是HTTP? HTTP 和 HTTPS 的区别?
文章目录 一、HTTP二、HTTPS三、区别参考文献 一、HTTP HTTP (HyperText Transfer Protocol),即超文本运输协议,是实现网络通信的一种规范 在计算机和网络世界有,存在不同的协议,如广播协议、寻址协议、路由协议等等… 而HTTP是…...
微信小程序如何进行npm导入组件
文章目录 目录 文章目录 前言 一、安装node 二、微信小程序通过npm安装组件(以Vant-weapp为例) 一、Vant-weapp下载 二 、修改 app.json 三 、修改 project.config.json 四 、 构建 npm 包 前言 微信小程序使用npm导入有很多的教程,我…...
MySQL编程实战LeetCode经典考题
文章简介 本文主要收集了LeetCode上关于MySQL的一些经典考题。 后续也会陆续把所有经典考题补充完整。 175.组合两个表 175.组合两个表 解答: select p.FirstName as firstName, p.LastName as lastName,a.City as city, a.State as state from Person p l…...
发生播放错误,即将重试 jellyfin
上周在家里的小主机上部署了jellyfin,真香,手机安卓端使用无问题,于是今天准备在电视上安装一个 首先是直接安装的手机版客户端,操作卡顿,而且很多操作没法实现,于是去下了一个tv版本 安装上后发现&#…...
BIONIOAIO
通信技术整体解决的问题 1.局域网内的通信要求 2.多系统间的底层消息传递机制 3.高并发下,大数据量的通信场景需要 4.游戏行业。无论是手游服务端、还是大型网络游戏,java的应用越来越广 IO模型基本说明 就是用什么样的通道或者说是通信模式和架构…...
SpringSecurity学习总结(三更草堂)
SpringSecurity安全框架的核心功能是认证和授权: 认证:验证当前访问系统的是不是本系统的用户,并且要确认具体是哪个用户。 授权:经过认证后判断当前用户是否具有进行某个操作的权限。 一般来说中大型的项目都是使用SpringSecurit…...
C++20中的jthread
一、多线程开发 c11以前,是不包含线程库的,开发多线程,必须使用OS系统自带的线程API,这就导致了很多问题,最主要的是,跨平台的开发,一般要保持几个主流应用的库的代码支持,特别是对…...
Xception模型详解
简介 Xception的名称源自于"Extreme Inception",它是在Inception架构的基础上进行了扩展和改进。Inception架构是Google团队提出的一种经典的卷积神经网络架构,用于解决深度卷积神经网络中的计算和参数增长问题。 与Inception不同࿰…...
【合合TextIn】AI构建新质生产力,合合信息Embedding模型助力专业知识应用
目录 一、合合信息acge模型获MTEB中文榜单第一 二、MTEB与C-MTEB 三、Embedding模型的意义 四、合合信息acge模型 (一)acge模型特点 (二)acge模型功能 (三)acge模型优势 五、公司介绍 一、合合信息…...
Flutter 拦截系统键盘,显示自定义键盘
一、这里记录下在开发过程中,下单的时候输入金额需要使用自定义的数字键盘 参考链接: https://juejin.cn/post/7166046328609308685 效果图 二、屏蔽系统键盘 怎样才能够在输入框获取焦点的时候,不让系统键盘弹出呢?同时又显示我们自定义的…...
内存泄漏是什么?如何避免内存泄漏?
1.2 内存泄漏 使用new开辟空间泄漏,抛出异常 int main() {int size 0;try{while (1){//int* p (int*)malloc(sizeof(int) * 1024 * 1024);/*if (p NULL){break;}*/int* p new int[1024 * 1024];size size 4 * 1024 * 1024;cout << p << endl;}}…...
linux 中的syslog的含义和用法
在Linux系统中,syslog是一种系统日志服务,用于收集、存储和管理系统和应用程序生成的日志消息。syslog服务负责记录系统的运行状态、错误信息、警告、调试信息等,以便系统管理员可以监控系统的健康状况、故障排查和性能优化。 含义和作用&am…...
kubernetes(K8S)学习(一):K8S集群搭建(1 master 2 worker)
K8S集群搭建(1 master 2 worker) 一、环境资源准备1.1、版本统一1.2、k8s环境系统要求1.3、准备三台Centos7虚拟机 二、集群搭建2.1、更新yum,并安装依赖包2.2、安装Docker2.3、设置hostname,修改hosts文件2.4、设置k8s的系统要求…...
巧克力(蓝桥杯)
文章目录 巧克力题目描述解题分析贪心 巧克力 题目描述 小蓝很喜欢吃巧克力,他每天都要吃一块巧克力。 一天小蓝到超市想买一些巧克力。超市的货架上有很多种巧克力,每种巧克力有自己的价格、数量和剩余的保质期天数,小蓝只吃没过保质期的…...
Python爬虫之pyquery和parsel的使用
三、pyquery的使用 1、准备工作 pip3 install pyquery2、初始化 2.1、字符串初始化 把HTML的内容当做参数,来初始化PyQuery对象。 html <div><ul><li class"item-0">first item</li><li class"item-1">&l…...
移动硬盘怎么加密?移动硬盘加密软件有哪些?
移动硬盘是我们在工作中最常用的移动存储设备,为了保护数据安全,需要使用专业的移动硬盘加密软件加密保护。那么,移动硬盘加密软件有哪些? BitLocker BitLocker是Windows的磁盘加锁功能,可以用于加密保护移动硬盘中…...
openEuler 22.03 安装 .NET 8.0
openEuler 22.03 安装 .NET 8.0 openEuler 22.03 安装 .NET 8.0 openEuler 22.03 安装 .NET 8.0 查看内核信息 [jeffPC-20240314EIAA ~]$ cat /proc/version Linux version 5.15.146.1-microsoft-standard-WSL2 (root65c757a075e2) (gcc (GCC) 11.2.0, GNU ld (GNU Binutils)…...
【转载】OpenCV ECC图像对齐实现与代码演示(Python / C++源码)
发现一个有很多实践代码的git 库,特记录下: 地址:GitHub - luohenyueji/OpenCV-Practical-Exercise: OpenCV practical exercise 作者博客地址:https://blog.csdn.net/LuohenYJ 已关注。 Items项目Resources1age_gender1基于深度学习识别人脸性别和年龄Model2OpenCV_dlib_…...
每日一题(相交链表 )
欢迎大家来我们主页进行指导 LaNzikinh-CSDN博客 160. 相交链表 - 力扣(LeetCode) 给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。 图示两个链表在节…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...
基础测试工具使用经验
背景 vtune,perf, nsight system等基础测试工具,都是用过的,但是没有记录,都逐渐忘了。所以写这篇博客总结记录一下,只要以后发现新的用法,就记得来编辑补充一下 perf 比较基础的用法: 先改这…...
【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表
1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...
SpringTask-03.入门案例
一.入门案例 启动类: package com.sky;import lombok.extern.slf4j.Slf4j; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.EnableCach…...
Mac下Android Studio扫描根目录卡死问题记录
环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中,提示一个依赖外部头文件的cpp源文件需要同步,点…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
音视频——I2S 协议详解
I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...
