Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 在实例化对象时,向解除分配的对象发送NSKeyValueNotifyObserver消息时,如何发生错误访问_Objective C_Cocoa_Exc Bad Access_Key Value Observing - Fatal编程技术网

Objective c 在实例化对象时,向解除分配的对象发送NSKeyValueNotifyObserver消息时,如何发生错误访问

Objective c 在实例化对象时,向解除分配的对象发送NSKeyValueNotifyObserver消息时,如何发生错误访问,objective-c,cocoa,exc-bad-access,key-value-observing,Objective C,Cocoa,Exc Bad Access,Key Value Observing,我们遇到了这个奇怪的问题。 当我们实例化一个对象时,我们还实例化了一个属于该对象的属性: -(instancetype)init { self = [super init]; if (self) { [self setDocument]; } return self; } -(void)setDocument: { _flatGraphicsArrayController = [[NSArrayController alloc] initWithCont

我们遇到了这个奇怪的问题。 当我们实例化一个对象时,我们还实例化了一个属于该对象的属性:

-(instancetype)init
{
   self = [super init];
   if (self) {
     [self setDocument];
   }
   return self;
}

-(void)setDocument:
{
   _flatGraphicsArrayController = [[NSArrayController alloc] initWithContent:doc.flattenedObjects];
}
…在设置
\u平面图形阵列控制器时,偶尔会发生
EXC\u BAD\u访问

调用堆栈:

已确定此崩溃是由向解除分配的对象发送
NSKeyValueNotifyObserver
消息引起的,该对象似乎正在观察对
FlatGraphicsRayController的更改

对我来说,这是非常混乱的,因为拥有这个属性的对象刚刚被实例化,所以怎么可能有任何东西在观察属性的变化呢

是否有人注册以观察特定的内存地址(如果它是这样工作的),然后
flatGraphicsArrayController
在释放观察者时以某种方式占用了内存中的空间?

某个对象(Object1)被添加为另一个对象(Object2)的观察者。在那之后的某个时候,Object1和Object2都被解除分配,但没有任何东西将Object1作为Object2的观察者删除。键值观察者的关系保持在两个对象之外(因为当添加KVO时,出于二进制兼容性的原因,不能向
NSObject
添加新的实例变量,因此它必须将其状态存储在一个副表中)

KVO应该在解除分配Object1时对此进行投诉。检查控制台日志

无论如何,在以后的某个时间,您将创建
NSArrayController
的实例。它恰好与Object2占用相同的地址。这意味着它匹配KVO关于Object1和Object2之间观察关系的内部信息。因此,实际上,失效的Object1现在正在观察您的阵列控制器。当其属性发生更改时,它会向Object1发送KVO更改通知。当然,Object1已经不存在了。根据其地址是否被重用,以及该地址是否为新对象的基址或其中的某个点,结果可能是崩溃或静默


要解决此问题,您需要在解除分配被观测对象或观测对象之前始终删除KVO观测值。

谢谢您的回答;这就是问题的症结所在。当不同类型的对象占用旧对象2的内存空间时会发生什么情况?不客气。我不知道你在问什么。在本例中,很可能“不同类型的对象占用旧对象2的内存空间”。这就是问题所在。所以KVO系统不关心正在观察的对象——如果它被释放并替换为不同类型的对象,而新对象发生了变化,它仍然会发送通知?e、 有东西在观察人和物体。此人被释放。一个Dog对象替换它在内存中的位置。Dog对象更改,原始观察者是否收到通知?或者,只有当Person对象被另一个人替换时,原始观察者才会收到通知吗?类型没有多大关系,没有。KVO确实会切换观察对象的类,以便与它们的setter和其他变化的访问器挂钩,但这不是对象生成更改通知的唯一方式。当使用KVC对它们进行变异时,或者如果它们显式地调用
-will/didChange…
方法等,它们就会这样做。您关注的是错误的事情。分析KVO在一个显然已经崩溃的场景中会做什么是毫无意义的。修复在解除分配任一对象之前移除观察器的失败,以及KVO在发生故障时的行为变得无关紧要。明白。事实上,我们找到了观测结果未能被移除的地方。这是因为在试图移除观察者的过程中,接收器为
nil
。但是现在我不明白为什么接收器变成了
nil
。如果你感兴趣的话,我还发布了另一个问题:再次感谢你在这里的时间:)谢谢