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开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的广阔舞台上,安卓和iOS这两大操作系统无疑是主角。它们各自拥有独特的特点和优势,为开发者提供了不同的开发环境和工具。本文将深入浅出地探讨安卓和iOS开发环境的主要差异,包括开发工具、编程语言、用户界面设计、性能优化以及市场覆盖等方面,旨在帮助初学者更好地理解两大平台的开发特点,并为他们选择合适的开发路径提供参考。通过比较分析,我们将揭示不同环境下的开发实践,以及如何根据项目需求和目标受众来选择最合适的开发平台。
43 2
|
2月前
|
安全 Android开发 数据安全/隐私保护
探索安卓与iOS的安全性差异:技术深度分析与实践建议
本文旨在深入探讨并比较Android和iOS两大移动操作系统在安全性方面的不同之处。通过详细的技术分析,揭示两者在架构设计、权限管理、应用生态及更新机制等方面的安全特性。同时,针对这些差异提出针对性的实践建议,旨在为开发者和用户提供增强移动设备安全性的参考。
105 3
|
18天前
|
开发工具 Android开发 Swift
安卓与iOS开发环境的差异性分析
【10月更文挑战第8天】 本文旨在探讨Android和iOS两大移动操作系统在开发环境上的不同,包括开发语言、工具、平台特性等方面。通过对这些差异性的分析,帮助开发者更好地理解两大平台,以便在项目开发中做出更合适的技术选择。
|
2月前
|
安全 Linux Android开发
探索安卓与iOS的安全性差异:技术深度分析
本文深入探讨了安卓(Android)和iOS两个主流操作系统平台在安全性方面的不同之处。通过比较它们在架构设计、系统更新机制、应用程序生态和隐私保护策略等方面的差异,揭示了每个平台独特的安全优势及潜在风险。此外,文章还讨论了用户在使用这些设备时可以采取的一些最佳实践,以增强个人数据的安全。
|
3月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
【8月更文挑战第20天】在移动应用开发的广阔天地中,Android和iOS两大平台各自占据着重要的位置。本文将深入探讨这两种操作系统的开发环境,从编程语言到开发工具,从用户界面设计到性能优化,以及市场趋势对开发者选择的影响。我们旨在为读者提供一个全面的比较视角,帮助理解不同平台的优势与挑战,并为那些站在选择十字路口的开发者提供有价值的参考信息。
|
2月前
|
IDE 开发工具 Android开发
安卓与iOS开发环境对比分析
本文将探讨安卓和iOS这两大移动操作系统在开发环境上的差异,从工具、语言、框架到生态系统等多个角度进行比较。我们将深入了解各自的优势和劣势,并尝试为开发者提供一些实用的建议,以帮助他们根据自己的需求选择最适合的开发平台。
39 1
|
3月前
|
开发框架 Android开发 Swift
安卓与iOS应用开发对比分析
【8月更文挑战第20天】在移动应用开发的广阔天地中,安卓和iOS两大平台各占半壁江山。本文将深入探讨这两大操作系统在开发环境、编程语言、用户界面设计、性能优化及市场分布等方面的差异和特点。通过比较分析,旨在为开发者提供一个宏观的视角,帮助他们根据项目需求和目标受众选择最合适的开发平台。同时,文章还将讨论跨平台开发框架的利与弊,以及它们如何影响着移动应用的开发趋势。
|
3月前
|
安全 搜索推荐 Android开发
安卓与iOS应用开发的对比分析
【8月更文挑战第20天】在移动应用开发领域,安卓和iOS两大平台各领风骚。本文通过深入探讨两者的开发环境、编程语言、用户界面设计、应用市场及分发机制等方面的差异,揭示了各自的优势和挑战。旨在为开发者提供决策支持,同时帮助理解为何某些应用可能优先选择在一个平台上发布。
41 2
|
3月前
|
开发工具 Android开发 Swift
安卓与iOS开发环境对比分析
在移动应用开发的大舞台上,安卓与iOS两大操作系统各占半壁江山。本文将深入浅出地比较两者的开发环境,从开发工具、编程语言到用户界面设计等多个维度进行剖析,旨在为初入行的开发者们提供一盏明灯,帮助他们选择适合自己的开发路径。通过实例分析和数据支持,我们将揭示这两个平台的独特优势和潜在挑战,以及它们如何影响应用的性能和用户体验。
66 1
|
3月前
|
开发框架 开发工具 Android开发
安卓与iOS开发环境对比分析
【8月更文挑战第7天】在移动应用开发的广阔天地中,安卓和iOS两大平台各据一方。本文将深入探讨这两个平台的异同,从开发环境、工具支持到市场定位等方面进行比较。我们将不涉及具体的代码示例,而是聚焦于开发生态的宏观视角,为即将踏入这一领域的开发者提供一个全面的视角。
88 6