观察 object w/ KVO 的变化,上下文指针似乎不适用于 void*,但适用于 NSString*

Observing changes to an object w/ KVO, context pointer doesn't seem to be working with a void*, but works with an NSString*

所以我有一个 MainController,
在 header 里面我有这个 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:例程,w/键@"color"

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

如果我用 NSString* 替换我的 void*,它会按我预期的那样工作。

void* 怎么可能存储了两个不同的地址?

编辑: 也许 void* 的值可以帮助

po kStrokeColorWellChangedContext的结果:

0x00000001005553e8

-observeValueForKey:po context的结果:

0x0000000100555ea0

objc[17775]: Method cache corrupted. This may be a message to an invalid object, or a memory error somewhere else.
objc[17775]: receiver 0x100555ea0, SEL 0x7fff899c8246, isa 0x100555ea0, cache > 0x100555eb0, buckets 0x100566160, mask 0x0, occupied 0x0
objc[17775]: receiver 0 bytes, buckets 0 bytes
objc[17775]: selector 'respondsToSelector:'

那里抛出的异常可能有提示,但我真的一点都不懂

编辑2: p 而不是 po

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

请注意,我pretty-very确信我正在调试正确的通知。
两个原因; keyPath 是唯一的,我看到该值是正确的。另外,如果我使用 NSString* 作为上下文,它会起作用

这对我有用 - kStrokeColorWellChangedContext "has" 两个地址:它在内存中的位置和它的值,它们都是一样的!所以 kStrokeColorWellChangedContext& kStrokeColorWellChangedContext 在整个程序中应该可以互换。

您是否尝试过单步执行 KVO 回调并查看 at/logging contextkStrokeColorWellChangedContext 的值?还有 keyPath?

问题是您将 kStrokeColorWellChangedContext 定义为 header 中的 static 变量。每个导入 header 的翻译单元(基本上是源文件)都将创建一个 separate 变量,因为它被声明为 static 这就是它的意思文件范围内的变量。

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

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

extern void * const kStrokeColorWellChangedContext;

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

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

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