Cocoa绑定+过滤谓词+自动重新排列内容=崩溃

时间:2012-08-19 06:01:32

标签: xcode cocoa nspredicate cocoa-bindings key-value-observing

我遇到一个问题,其中一些简单的Cocoa绑定正在改变附加到具有Auto Rearrange Content set的ArrayController的fetch谓词。

我的数据模型有三个类(我们称之为A,B和C)。它以严格的层次结构排列,其中class_A的实例拥有一个或多个class_B实例,每个实例拥有一个或多个class_C实例;并且B类和C类的每个实例都对其父类具有弱引用。例如:

@interface Class_A
@property (strong) NSArray *collection_of_b;
@property BOOL foo;
@end

@interface Class_B
@property (weak) Class_A class_A;
@property (strong) NSArray *collection_of_c;
@property (weak) SomeOtherClass bar;
@end

@interface Class_C
@property (weak) Class_B class_B;
@property (weak) SomeOtherClass baz;
@end

我在大型主 - 详细视图中显示此层次结构。第一个表视图包含所有class_A实例的列表;在选择时,第二个表视图显示class_B实例的列表;并在再次选择时,第三个表视图显示class_C实例列表。

在每个列表下方,有一组字段绑定到所选class_A,class_B或class_C(如foo,bar和baz)的各种属性。这些字段要么使用严格的KVO兼容访问器来修改类成员,要么我只是将字段直接绑定到选择成员。 (例如,class_A.foo绑定到YES和NO的一组单选按钮。)所有这些看起来都很完美。

现在,这是踢球者。在同一个窗口的另一部分中,我将展示一个具有一些属性的class_C实例的过滤列表。为了呈现该筛选列表,我使用过滤谓词指定一些条件,如“(class_B.bar == some value)OR(class_B.class_A.foo == YES)”。过滤效果非常好...直到我通过绑定字段更改foo或bar的值,当我的应用程序立即崩溃时出现以下消息:

“无法从< Class_B实例>中移除关键路径”bar“的观察者,很可能是因为键”bar“的值已更改而未发送相应的KVO通知。请检查KVO合规性Class_B类。“

我已将问题缩小到ArrayController的Auto Rearrange Content设置。当我关闭它时,表格不会在实例的过滤属性发生变化时自动调整内容,但也不会崩溃。当然,我可以手动触发重新排列,但这是一个不优雅的解决方案。

一些搜索显示2009年的cocoa-dev线程报告了自动排列内容与错误完全相同的行为:

https://groups.google.com/forum/?hl=en&fromgroups#!topic/cocoa-dev/SpXF0__B4dE

不知道可以做些什么。有什么想法吗?

1 个答案:

答案 0 :(得分:1)

我猜你问题的根源在这里:

@property (weak) SomeOtherClass bar;

@property (weak) Class_B class_B;

当这些对象被释放时,运行时将它们的实例变量设置为nil,但不会发出KVO通知。

尝试将这些属性更改为strong属性,看看是否能解决问题。

有一些good, but complex explanation about this situation in this blog post