在Objective C中禁用键值观察

时间:2013-04-05 10:11:14

标签: ios objective-c performance key-value-observing

我不使用KVO,主要是出于性能原因,所以我想确保我正确地禁用它。

从Apple Key-Value Observing Programming Guide

  

自动支持(对于KVO)由NSObject提供,默认情况下可用于符合键值编码的类的所有属性。通常,如果您遵循标准的Cocoa编码和命名约定,则可以使用自动更改通知 - 您不必编写任何其他代码。

这是否意味着Xcode生成的每个属性都实现了willChangeValueForKeydidChangeValueForKey方法?

如果有,有某种方式(某些标志或某事)来禁用此行为? 我正在使用accessInstanceVariablesDirectly并且总是返回NO,但我不确定这是否足够好。

5 个答案:

答案 0 :(得分:9)

  

我不使用KVO。

你真的不知道。 Cocoa框架类或其他外来代码可能在您不知情的情况下依赖于KVO。

此外,NSObject的KVO使用一种称为isa-swizzling的技术,通过动态子类化来自动增强观察对象。这意味着没有观察到的对象没有开销。

您的其他问题:

accessInstanceVariablesDirectly仅用于KVC,未连接到KVO。覆盖它没有任何性能优势。

  

这是否意味着Xcode生成的每个属性都有   willChangeValueForKeydidChangeValueForKey方法   执行吗?

是的,每个对象都会响应这些方法。但这些方法的存在并不意味着性能会受到任何影响。通常甚至不会调用这些方法。

答案 1 :(得分:3)

简而言之:

通常,从外部访问对象时使用属性。然后,性能不应该是至关重要的,因为你可能没有繁重的工作。如果KVO是一个问题,您可能需要检查应用程序的设计。 从对象本身来看,最好直接访问ivars,在这种情况下KVO是无关紧要的。

更多详情:

最近在苹果邮件列表上讨论过这个话题:
When to use properties vs. ivars

尤其是Jens Alfke(前苹果公司)的答案 雇员):

  
      
  • 作为班级公共API的一部分。
  •   
  • 作为类实现的抽象
  •   
  • 作为更改实例变量的方便瓶颈 - 例如,如果您想在每次更改时触发其他内容   变量,将它设置为属性而不是写入是有用的   直接到伊塔尔。
  •   
  • 在非ARC代码中,当您分配新值时,它可以是管理保留/释放舞蹈的便捷方式(但此问题仍然存在)   远离ARC。)
  •   
     

我见过只声明并使用所有属性的代码   内部状态 - 我认为这是一个坏主意。这真的很浪费   CPU时间和代码大小,它不再给你买任何东西   现在我们有了ARC。

另外,请注意除了KVO之外还有其他性能问题。 John McCall(现任Apple员工)表示:

  

属性以多种方式影响性能:

     
      
  1. 如前所述,发送消息以进行加载/存储的速度较慢   而不仅仅是内联加载/存储。
  2.   
  3. 发送消息以进行加载/存储也需要在i-cache中保存更多代码:即使添加了getter / setter   除了加载/存储之外的零额外指令,还有一个可靠的   调用者中有6个额外的指令来设置消息发送   并处理结果。
  4.   
  5. 发送消息会强制将该选择器的条目保留在方法高速缓存中,并且该内存通常会在d-cache中保留。   这会增加启动时间,增加您的静态内存使用量   应用程序,并使上下文切换更痛苦。由于方法缓存   特定于对象的动态类,这个问题增加了   您使用KVO的次数越多。
  6.   
  7. 发送消息强制将函数中的所有值溢出到堆栈中(或保存在callee-save寄存器中,这只是意味着   在不同的时间溢出。)
  8.   
  9. 发送消息可能会产生任意副作用,因此会强制编译器重置所有关于非本地的假设   存储器中。
  10.   
  11. 发送消息可能会产生任意副作用,因此无法提升,沉没,重新订购,合并或消除。
  12.   
  13. 在ARC中,消息发送的结果将始终由被调用者或调用者保留,即使是+0返回:即使   方法不保留/自动释放其结果,调用者不知道   那并且必须尝试采取行动以防止结果得到   自动释放。这是永远无法消除的,因为消息发送是   不是静态可分析的。
  14.   
  15. 在ARC中,因为setter方法通常将其参数设置为+0,所以没有办法将该对象的保留(如上所述,ARC通常具有)转移到ivar中,因此值   通常必须保留/释放两次。
  16.         

    这些都不意味着它们总是坏的,当然 - 有一个   使用属性的很多好理由。请记住,就像   许多其他语言功能,他们不是免费的。

超越KVO,在设计应用程序时应考虑这些因素。

答案 2 :(得分:2)

  

这是否意味着Xcode生成的每个属性都实现了willChangeValueForKey和didChangeValueForKey方法?

没有。除了Xcode不是由编译器生成属性这一事实外,这意味着默认情况下可以自动观察常规命名的属性,如果需要,可以实现KVO方法 这并不意味着每次设置属性时,都会调用类中的各种方法。只有您指定的那些。

所以,基本上,不要担心这个。仅仅由KVO引入了性能影响。

答案 3 :(得分:1)

我不认为这会以任何方式影响性能。因此,如果您不想使用它,可以忽略KVO。

当您使用addObserver观察KV变化时,观察将仅启动并因此使用资源。

答案 4 :(得分:0)

您可以查看+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key。它是一个类方法,而不是实例,并将配置一个类型的所有对象。

除了您的要求之外,当您需要手动KVO而不是自动KVO时,这非常有用。

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Protocols/NSKeyValueObserving_Protocol/#//apple_ref/occ/clm/NSObject/automaticallyNotifiesObserversForKey