前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >iOS-探索KVO|隐秘的角落

iOS-探索KVO|隐秘的角落

作者头像
用户6256742
发布2024-06-28 10:18:04
460
发布2024-06-28 10:18:04
举报
文章被收录于专栏:网络日志网络日志

Hi 👋

我的个人项目

扫雷Elic 无尽天梯

梦见账本

类型

游戏

财务

AppStore

Elic

Umemi

前言

KVO 在开发中还是经常使用的,但是有些隐秘的角落却经常被忽视,本文将对这些角落进行一些探究。

⚠️重要说明

Important: In order to understand key-value observing, you must first understand key-value coding.

一、 Options

它影响通知中提供的更改字典的内容以及生成通知的方式。

NSKeyValueObservingOptionOld

更改之前的值

NSKeyValueObservingOptionNew

接收新值

NSKeyValueObservingOptionInitial

您指示被观察对象使用选项 NSKeyValueObservingOptionInitial 发送立即更改通知(在 addObserver:forKeyPath:options:context:returns 之前)。您可以使用这个额外的一次性通知来获取初始值。

NSKeyValueObservingOptionPrior

您可以通过包含选项 NSKeyValueObservingOptionPrior 指示被观察对象在属性更改之前发送通知(除了更改之后的通常通知之外)。

变更字典通过包含键 NSKeyValueChangeNotificationIsPriorKey 和包含 YESNSNumber 值来表示预更改通知。

可以通过这些选项的按位枚举接收多种

二、 Context

代码语言:javascript
复制
[tool.ryuk addObserver:tool forKeyPath:@"name" options:NSKeyValueObservingOptionNew context:NULL];

在平时使用时,我们一般就传个 NULL 但是他到底是做什么的有想过么?

addObserver:forKeyPath:options:context: 消息中的 Context 指针可以包含任意数据,这些数据将在相应的更改通知中传递回观察者。您可以指定 NULL 并完全依赖键路径字符串来确定更改通知的来源,但是这种方法可能会导致对象的父类由于不同原因也在观察相同的键路径时出现问题。

一种更安全、更可扩展的方法是使用 Context 来确保您收到的通知是发送给您的观察者而不是父类的。

类中唯一命名的静态变量的地址是一个很好的 Context 。在父类或子类中以类似方式选择的 Context 不太可能重叠。您可以为整个类选择一个 Context ,并依靠通知消息中的关键路径字符串来确定发生了什么变化。

或者,您可以为每个观察到的键路径创建一个不同的 Context ,这完全绕过了字符串比较,从而提高了通知解析的效率。

创建 Context 指针

代码语言:javascript
复制
static void *PersonAccountBalanceContext = &PersonAccountBalanceContext;
static void *PersonAccountInterestRateContext = &PersonAccountInterestRateContext;

注册观察者

代码语言:javascript
复制
- (void)registerAsObserverForAccount:(Account*)account {
    [account addObserver:self
              forKeyPath:@"balance"
                 options:(NSKeyValueObservingOptionNew |
                          NSKeyValueObservingOptionOld)
                 context:PersonAccountBalanceContext];
 
    [account addObserver:self
              forKeyPath:@"interestRate"
                 options:(NSKeyValueObservingOptionNew |
                          NSKeyValueObservingOptionOld)
                  context:PersonAccountInterestRateContext];
}

三、 对可变数组的观察

iOS-探索KVO|隐秘的角落
iOS-探索KVO|隐秘的角落

相对可变数组进行 KVO 很可能会写出这样的代码。但是明显是没用的。这就不得不提文章开始的那句官方提示 重要:为了能理解 KVO ,必须先理解 KVC。

访问集合属性 Accessing Collection Properties有提到,为了使可变集合内部的变化,能够被监听到需要调整一下 API

  • mutableArrayValueForKey: and mutableArrayValueForKeyPath:
    • return NSMutableArray
  • mutableSetValueForKey: and mutableSetValueForKeyPath:
    • return NSMutableSet
  • mutableOrderedSetValueForKey: and mutableOrderedSetValueForKeyPath:
    • return NSMutableOrderedSet
iOS-探索KVO|隐秘的角落
iOS-探索KVO|隐秘的角落

四、 KVO 开关控制

如果你写了一个库,不希望内部的一些属性被监听到。有没有办法阻止掉呢?

代码语言:javascript
复制
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key;

系统提供了上面的方法,默认是返回 YES,即:所有属性都可以被监听。如果你不希望部分或者全部被监听可以返回 NO

4.1 全部禁止

iOS-探索KVO|隐秘的角落
iOS-探索KVO|隐秘的角落

没有触发变动的通知

4.2 部分禁止

iOS-探索KVO|隐秘的角落
iOS-探索KVO|隐秘的角落

name 的通知没有触发,books 的通知正常触发了。

4.3 禁止后手动发送通知

iOS-探索KVO|隐秘的角落
iOS-探索KVO|隐秘的角落

虽然 automaticallyNotifiesObserversForKey 禁止了通知,但是手动触发后依旧可以正常监听到

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-06-07 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Hi 👋
  • 前言
    • ⚠️重要说明
    • 一、 Options
      • NSKeyValueObservingOptionOld
        • NSKeyValueObservingOptionNew
          • NSKeyValueObservingOptionInitial
            • NSKeyValueObservingOptionPrior
            • 二、 Context
            • 三、 对可变数组的观察
            • 四、 KVO 开关控制
              • 4.1 全部禁止
                • 4.2 部分禁止
                  • 4.3 禁止后手动发送通知
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档