我不使用KVO,主要是出于性能原因,所以我想确保我正确地禁用它。
从Apple Key-Value Observing Programming Guide
自动支持(对于KVO)由NSObject提供,默认情况下可用于符合键值编码的类的所有属性。通常,如果您遵循标准的Cocoa编码和命名约定,则可以使用自动更改通知 - 您不必编写任何其他代码。
这是否意味着Xcode生成的每个属性都实现了willChangeValueForKey
和didChangeValueForKey
方法?
如果有,有某种方式(某些标志或某事)来禁用此行为?
我正在使用accessInstanceVariablesDirectly
并且总是返回NO,但我不确定这是否足够好。
答案 0 :(得分:9)
我不使用KVO。
你真的不知道。 Cocoa框架类或其他外来代码可能在您不知情的情况下依赖于KVO。
此外,NSObject的KVO使用一种称为isa-swizzling的技术,通过动态子类化来自动增强观察对象。这意味着没有观察到的对象没有开销。
您的其他问题:
accessInstanceVariablesDirectly
仅用于KVC,未连接到KVO。覆盖它没有任何性能优势。
这是否意味着Xcode生成的每个属性都有
willChangeValueForKey
和didChangeValueForKey
方法 执行吗?
是的,每个对象都会响应这些方法。但这些方法的存在并不意味着性能会受到任何影响。通常甚至不会调用这些方法。
答案 1 :(得分:3)
简而言之:
通常,从外部访问对象时使用属性。然后,性能不应该是至关重要的,因为你可能没有繁重的工作。如果KVO是一个问题,您可能需要检查应用程序的设计。 从对象本身来看,最好直接访问ivars,在这种情况下KVO是无关紧要的。
更多详情:
最近在苹果邮件列表上讨论过这个话题:
When to use properties vs. ivars
尤其是Jens Alfke(前苹果公司)的答案 雇员):
- 作为班级公共API的一部分。
- 作为类实现的抽象
- 作为更改实例变量的方便瓶颈 - 例如,如果您想在每次更改时触发其他内容 变量,将它设置为属性而不是写入是有用的 直接到伊塔尔。
- 在非ARC代码中,当您分配新值时,它可以是管理保留/释放舞蹈的便捷方式(但此问题仍然存在) 远离ARC。)
我见过只声明并使用所有属性的代码 内部状态 - 我认为这是一个坏主意。这真的很浪费 CPU时间和代码大小,它不再给你买任何东西 现在我们有了ARC。
另外,请注意除了KVO之外还有其他性能问题。 John McCall(现任Apple员工)表示:
属性以多种方式影响性能:
- 如前所述,发送消息以进行加载/存储的速度较慢 而不仅仅是内联加载/存储。
- 发送消息以进行加载/存储也需要在i-cache中保存更多代码:即使添加了getter / setter 除了加载/存储之外的零额外指令,还有一个可靠的 调用者中有6个额外的指令来设置消息发送 并处理结果。
- 发送消息会强制将该选择器的条目保留在方法高速缓存中,并且该内存通常会在d-cache中保留。 这会增加启动时间,增加您的静态内存使用量 应用程序,并使上下文切换更痛苦。由于方法缓存 特定于对象的动态类,这个问题增加了 您使用KVO的次数越多。
- 发送消息强制将函数中的所有值溢出到堆栈中(或保存在callee-save寄存器中,这只是意味着 在不同的时间溢出。)
- 发送消息可能会产生任意副作用,因此会强制编译器重置所有关于非本地的假设 存储器中。
- 发送消息可能会产生任意副作用,因此无法提升,沉没,重新订购,合并或消除。
- 在ARC中,消息发送的结果将始终由被调用者或调用者保留,即使是+0返回:即使 方法不保留/自动释放其结果,调用者不知道 那并且必须尝试采取行动以防止结果得到 自动释放。这是永远无法消除的,因为消息发送是 不是静态可分析的。
- 在ARC中,因为setter方法通常将其参数设置为+0,所以没有办法将该对象的保留(如上所述,ARC通常具有)转移到ivar中,因此值 通常必须保留/释放两次。
醇>这些都不意味着它们总是坏的,当然 - 有一个 使用属性的很多好理由。请记住,就像 许多其他语言功能,他们不是免费的。
超越KVO,在设计应用程序时应考虑这些因素。
答案 2 :(得分:2)
这是否意味着Xcode生成的每个属性都实现了willChangeValueForKey和didChangeValueForKey方法?
没有。除了Xcode不是由编译器生成属性这一事实外,这意味着默认情况下可以自动观察常规命名的属性,如果需要,可以实现KVO方法 这并不意味着每次设置属性时,都会调用类中的各种方法。只有您指定的那些。
所以,基本上,不要担心这个。仅仅由KVO引入了性能影响。
答案 3 :(得分:1)
我不认为这会以任何方式影响性能。因此,如果您不想使用它,可以忽略KVO。
当您使用addObserver
观察KV变化时,观察将仅启动并因此使用资源。
答案 4 :(得分:0)
您可以查看+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key
。它是一个类方法,而不是实例,并将配置一个类型的所有对象。
除了您的要求之外,当您需要手动KVO而不是自动KVO时,这非常有用。