iOS探索 -- KVO 的原理分析

简介: KVO (key-value-observing) 是一种 键值观察 机制, 它允许当前对象去观察目标对象的某个属性的变化; 当被观察对象的属性发生变化后, 会通过特定方法通知观察者对象属性变化的一些情况内容, 观察者对象拿到变化情况后做出相关操作。

什么是 KVO?
KVO (key-value-observing) 是一种 键值观察 机制, 它允许当前对象去观察目标对象的某个属性的变化; 当被观察对象的属性发生变化后, 会通过特定方法通知观察者对象属性变化的一些情况内容, 观察者对象拿到变化情况后做出相关操作。
关于 KVO 的一些详细介绍可以去 苹果官方文档 了解一下, 这里就不做过多介绍了。
KVO 的初探
进行探索之前, 首先看看 KVO 是怎么使用的:
 // 方法
 - (void)addObserver:(NSObject *)observer
    forKeyPath:(NSString *)keyPath
             options:(NSKeyValueObservingOptions)options
             context:(nullable void *)context;
 // 日常使用
 [self.person addObserver:self
               forKeyPath:@"name"
                  options:(NSKeyValueObservingOptionNew)
                  context:NULL];
复制代码

self.person : 也就是方法调用者, 就是被观察属性 name 的对象 (被观察者)
observer : 观察者, 上面例子中的 self
options : 观察的模式, 是个枚举类型, 总共有 4 种观察模式: NSKeyValueObservingOptionNew 、 NSKeyValueObservingOptionOld 、NSKeyValueObservingOptionInitial 和 NSKeyValueObservingOptionPrior
context : 在上面的使用中传的是一个 NULL , 因为它的参数类型是 void * 是一个指针 (虽然传 nil 也没有问题, 但是严格来说的话应该传 NULL 吧)。我们平时好像没有怎么关注过它, 它是用来干什么的呢, 来看看官方文档。

  1. context 是什么

首先来看看官方文档里关于 context 的相关介绍:
 The context pointer in the addObserver:forKeyPath:options:context: message contains arbitrary data that will be passed back to the observer in the corresponding change notifications. You may specify NULL and rely entirely on the key path string to determine the origin of a change notification, but this approach may cause problems for an object whose superclass is also observing the same key path for different reasons.
 A safer and more extensible approach is to use the context to ensure notifications you receive are destined for your observer and not a superclass.
 // 大概意思是
 // addObserver:forKeyPath:options:context:message中的上下文指针包含相应的更改通知中将要传递回观察者的任意数据。您可以指定NULL,并完全依赖键路径字符串来确定更改通知的来源,但这种方法可能会导致其父类出于不同原因也在观察同样的键路径的情况出现问题。
 // 一种更安全、更可扩展的方法是使用上下文来确保您收到的通知是针对您的观察者的,而不是父类的。
复制代码
大概就是在多个观察者的情况下, 有可能不同的类 (上面说的是父类) 拥有相同的 keyPath , 这样在修改信息回来的时候就会导致无法判断到底是那个被观察对象的属性发生了改变。
通过使用 context 字段, 可以更清楚的辨别当前的通知信息是发送给哪一个 观察者 的。当然, 如果不存在上述注释中说的那种情况下, 使用 NULL 是不会有影响的。

  1. 移除观察者

 // Asking to be removed as an observer if not already registered as one results in an NSRangeException.
 // 如果尚未注册为观察员,则请求以观察员身份删除会导致NSRangeException。
复制代码

在没有添加过观察者的情况下去调用移除观察者方法会造成程序崩溃, 必须添加过之后才能调用移除方法

 // ensuring properly paired and ordered add and remove messages, and that the observer is unregistered before it is freed from memory.
 // 应该确保正确配对并按顺序添加和删除消息,并确保在从内存中释放观察者之前将其注销。
复制代码

添加观察者和移除观察者必须是 成对出现并且有先后顺序的 , 也就是在不需要使用后必须保证观察者被移除掉, 下面来举个例子说明一下:

 // 单例类 Person
 @interface Person : NSObject
 @property (nonatomic, copy) NSString *name;
 + (instancetype)shareInstance;
 @end
 // 控制器 A
 [self.person addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionNew) context:NULL];
 // 控制器 B (A 跳转到 B)
 [self.person addObserver:self forKeyPath:@"name" options:(NSKeyValueObservingOptionNew) context:NULL];
复制代码
具体步骤:

首先有一个单例 Person , 在 控制器 A 中添加观察者观察 name 属性, 控制器 A 跳转到 控制器 B
控制器 B 也添加观察者观察 name 属性, 在 B 返回上一级页面 (也就是被销毁的时候) 时应该调用 remove 方法将观察者移除掉
如果 B 在返回的时候没有移除观察者, 在 A 再次修改 name 属性的时候就会引发崩溃触发野指针异常 Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)

相关文章
|
2月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
212 4
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
4月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统无疑是主角。它们各自拥有独特的特点和优势,为开发者提供了不同的开发环境和工具。本文将深入浅出地探讨安卓和iOS开发环境的主要差异,包括开发工具、编程语言、用户界面设计、性能优化以及市场覆盖等方面,旨在帮助初学者更好地理解两大平台的开发特点,并为他们选择合适的开发路径提供参考。通过比较分析,我们将揭示不同环境下的开发实践,以及如何根据项目需求和目标受众来选择最合适的开发平台。
57 2
|
1月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
32 8
|
2月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
45 1
|
4月前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
163 3
|
3月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
4月前
|
安全 Linux Android开发
探索安卓与iOS的安全性差异:技术深度分析
本文深入探讨了安卓(Android)和iOS两个主流操作系统平台在安全性方面的不同之处。通过比较它们在架构设计、系统更新机制、应用程序生态和隐私保护策略等方面的差异,揭示了每个平台独特的安全优势及潜在风险。此外,文章还讨论了用户在使用这些设备时可以采取的一些最佳实践,以增强个人数据的安全。
|
5月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
【8月更文挑战第20天】在移动应用开发的广阔天地中,Android和iOS两大平台各自占据着重要的位置。本文将深入探讨这两种操作系统的开发环境,从编程语言到开发工具,从用户界面设计到性能优化,以及市场趋势对开发者选择的影响。我们旨在为读者提供一个全面的比较视角,帮助理解不同平台的优势与挑战,并为那些站在选择十字路口的开发者提供有价值的参考信息。
111 17
|
4月前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
本文将探讨安卓和iOS这两大移动操作系统在开发环境上的差异,从工具、语言、框架到生态系统等多个角度进行比较。我们将深入了解各自的优势和劣势,并尝试为开发者提供一些实用的建议,以帮助他们根据自己的需求选择最适合的开发平台。
59 1