观察对具有KVO的对象的更改,上下文指针似乎不使用void *,但使用NSString *

时间:2015-10-05 19:06:25

标签: objective-c key-value-observing void-pointers

所以我有一个 MainController
在标题内部,我声明了void*

static void *kStrokeColorWellChangedContext = &kStrokeColorWellChangedContext;

我正在处理观察的实现内部:

-(void)observeValueForKeyPath:(NSString *)keyPath
                     ofObject:(id)object
                       change:(NSDictionary *)change
                      context:(void*)context
{
   if( [keyPath isEqualToString:@"color"] )
   {
      if( context == kStrokeColorWellChangedContext )
      {
         [self setValue:[change objectForKey:@"new"] forKey:@"strokeColor"];
      }
   }

然后我有一个 ViewController ,它有一行,它将 MainController 作为观察者添加到视图中

[self.strokeColorWell addObserver:self.toolController forKeyPath:@"color" options:NSKeyValueObservingOptionNew context:kStrokeColorWellChangedContext];

因此,当视图的颜色发生变化时,它会通知 MainController ,并输入-observeValueForKey:例程,其中包含密钥@"color"

但它无法进入内部if区块,我正在检查context

如果我要用void*代替我NSString*,它会按照我的预期运作。

void*怎么可能有两个不同的地址存储在其中?

修改 也许void*的值可以帮助

po kStrokeColorWellChangedContext的结果:

  

0x00000001005553e8

po context-observeValueForKey:的结果:

  

0x0000000100555ea0

     

objc [17775]:方法缓存已损坏。这可能是一条消息   无效的对象,或其他地方的内存错误   objc [17775]:接收器0x100555ea0,SEL 0x7fff899c8246,isa 0x100555ea0,cache> 0x100555eb0,桶0x100566160,掩码0x0,占用0x0
  objc [17775]:接收器0字节,桶0字节
  objc [17775]:selector' respondsToSelector:'

抛出的异常可能会有一些提示,但我真的不理解其中任何一个

EDIT2: p而不是po

的输出
(lldb) p context
(void *) $5 = 0x0000000100555ea0
(lldb) p kStrokeColorWellChangedContext
(void *) $6 = 0x00000001005553e8

请注意,我非常有信心我正在调试正确的通知 两个原因; keyPath是唯一的,我看到这个值是正确的。此外,如果我使用NSString*作为上下文,则可以使用

2 个答案:

答案 0 :(得分:5)

问题是您在标头中将kStrokeColorWellChangedContext定义为static变量。导入该标题的每个翻译单元(基本上是源文件)将按该名称创建单独的变量,因为它声明为static,这就是文件范围内变量的含义。

因此,每个变量都有一个单独的地址,因为变量的值是它自己的地址,每个变量都有不同的值。

您可以在标头中声明变量并在实现中定义它,以便只有一个这样的变量。标题中的声明如下所示:

extern void * const kStrokeColorWellChangedContext;

其中一个实现文件中的定义如下所示:

void * const kStrokeColorWellChangedContext = (void*)&kStrokeColorWellChangedContext;

请注意,我已将变量指向void const。这不允许为它分配新值,因为它应该是一个常量。

答案 1 :(得分:1)

这对我有用 - kStrokeColorWellChangedContext"有"两个地址:它在记忆中的位置和它的价值,它们都是一样的!因此kStrokeColorWellChangedContext& kStrokeColorWellChangedContext在您的整个计划中应该可以互换。

您是否尝试单步执行KVO回调并查看/记录contextkStrokeColorWellChangedContext的值?并keyPath