Objective c 观察对象的变化w/KVO,上下文指针不';t似乎使用的是void*,但使用的是NSString*

Objective c 观察对象的变化w/KVO,上下文指针不';t似乎使用的是void*,但使用的是NSString*,objective-c,key-value-observing,void-pointers,Objective C,Key Value Observing,Void Pointers,所以我有一个主控制器, 在标题内部,我声明了以下内容:void*: static void *kStrokeColorWellChangedContext = &kStrokeColorWellChangedContext; 在实施过程中,我正在处理观察: -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object ch

所以我有一个主控制器
在标题内部,我声明了以下内容:
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];
因此,当视图的颜色发生变化时,它会通知主控制器,并进入
-observeValueForKey:
例程,使用键
@“color”

但它无法进入内部
if
块,我正在检查
上下文

如果我用一个
NSString*
替换掉我的
void*
,它会像我期望的那样工作

void*
中存储了两个不同的地址,这怎么可能呢

编辑: 也许
void*
的值会有所帮助

po kStrokeColorWellChangedContext的结果

0x00000001005553e8

-observeValueForKey:
中的
po上下文的结果:

0x0000000100555ea0

objc[17775]:方法缓存已损坏。这可能是一条发送给用户的消息 无效对象,或其他地方出现内存错误。
objc[17775]:接收器0x100555ea0,SEL 0x7fff899c8246,isa 0x100555ea0,缓存>0x100555eb0,存储桶0x100566160,掩码0x0,占用0x0
objc[17775]:接收器0字节,存储桶0字节
objc[17775]:选择器“响应选择器:”

抛出的异常可能是一个暗示,但我真的一点都不明白

EDIT2:
p
而不是
po

(lldb) p context
(void *) $5 = 0x0000000100555ea0
(lldb) p kStrokeColorWellChangedContext
(void *) $6 = 0x00000001005553e8
请注意,我非常确信我正在调试正确的通知。

原因有二;
keyPath
是唯一的,我认为该值是正确的。另外,如果我使用一个
NSString*
作为上下文,它对我有效-
kStrokeColorWellChangedContext“有”两个地址:它在内存中的位置和它的值,它们都是相同的!因此,在整个程序中,
kStrokeColorWellChangedContext
&kStrokeColorWellChangedContext
应该是可互换的


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

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

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

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

extern void * const kStrokeColorWellChangedContext;
void * const kStrokeColorWellChangedContext = (void*)&kStrokeColorWellChangedContext;
其中一个实现文件中的定义如下所示:

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

注意,我将变量a
const
指针设为void。这不允许为它赋值,因为它应该是一个常量。

您的
静态void
行中似乎有一个输入错误。
=
的两侧引用相同的变量名。这可能不是你想要做的。我知道这看起来很奇怪,但这似乎是Nhipster上所支持的方式-虽然在这种情况下没有显示addObserver代码,但是有或没有-,这应该是相同的-,你不能将
po
context
参数一起使用,因为
context
不是对象。这就是为什么你看到一条错误消息说“这可能是给无效对象的消息…”是的,这是我的错误,我一直认为
po
代表“打印输出”哈哈。感谢您的更正,我已经编辑了带有更改的问题,但是,与字符串值进行比较不是更简单,并且有助于避免这种混淆吗?我测试的范围是检查传递到
-observeValue
中的
上下文的值。然后在
lldb
中,我键入了
pokstrokecolorwellchangedcontext
。这两个值不相同,我可以确认视图正在向主控制器发送通知,因为如果我交换上下文,我将用字符串传递到
-addObserver
,我可以看到
context
的值是字符串,没有添加其他观察者吗?是的,实际上--我在另一个视图中有完全相同的设置,除了名为kFillColorWellChangedContext的上下文外,所有内容都是相同的。但是这个上下文值与传递到
observeValue
上下文不一样,我也可以删除它,同样的问题仍然存在。非常混乱,因为我们在工作区的其他地方使用了这种模式,而且效果很好。我会尝试删除另一个观察者。我还要检查视图是否是您期望的视图No go:\并确保视图是我期望的视图。编辑问题以包含调试结果这是正确答案-我错过了“标题”部分。很好。太棒了,谢谢你把它分解并解释——包括
const
关键字。如果您有时间,可以问一个简单的问题:您提到导入标题的每个翻译单元都将创建一个单独的变量。但我记得读过这样一篇文章,即“导入”确保一个文件只包含一次。所以,如果我总是使用“导入”
,那么您知道这是如何工作的吗?每个翻译单元都导入了您的标题。它只进口我