核心数据:重新打开文档时出现奇怪的绑定错误。帮助?
Posted
技术标签:
【中文标题】核心数据:重新打开文档时出现奇怪的绑定错误。帮助?【英文标题】:Core Data: Strange bindings error on re-opening a document. Help? 【发布时间】:2009-06-22 18:22:46 【问题描述】:我一直在构建一个核心数据应用程序来管理一些数据,但我被一个表明我的对象不符合 KVO 的错误所困扰。但是,我还没有修改 NSManagedObject 的默认 KVO 合规性,现在我只能摸不着头脑了。
该错误影响的应用程序区域是创建一些类别并组织将存在于这些类别中的一些项目。项目可能存在多个类别,用户可以设置项目和类别查看顺序。简单的东西。
为了更好地可视化这一点,我设置的核心数据模型的关键部分如下所示。我稍微简化了实体的命名和属性:
Category <--------->> CategoryItem <<---------> Item
-------- ------------ --------
name viewPosition name
viewPosition description
这个模型在interface builder中连接了两个ArrayController,一个用于category,一个用于categoryitems。 categoryitems 内容集通过 selection.categoryItems 绑定设置为类别数组控制器。这些数组控制器提供两个表视图。 category items表的内容通过arrangedObjects.item.name绑定到CategoryItem A.C控制器。
这一切都完美无缺,我正在根据自己的心愿拖放和排序项目和类别。
除了一个奇怪的案例。
每当我创建一个只有一个项目的类别时,然后保存,如果我随后重新打开该文档,则会出现以下错误:
无法从<NSManagedObject 0x16273380>
中删除键路径“item.name”的观察者<NSTableBinder 0x1627f670>
,很可能是因为键“item”的值已更改而未发送适当的KVO 通知。检查 NSManagedObject 类的 KVO 兼容性。
之后界面似乎崩溃了,应用程序变得无法使用。我在网上搜索过,我所能发现的只是这表明 KVC 不合规。但我在这里使用的是标准的、几乎没有修改过的 Apple 类。
当我仅绑定到 CategoryItem 的 viewPosition 时,该错误不会引发。即通过排列对象.viewPosition 而不是排列对象.item.name。就好像 categoryitem 和 item 之间的关系在表格最初观察到的那一点上还没有准备好(并且仅当有一个 item 时)。
有没有其他人遇到过这种情况?谁能想到一个可能的解决方法?
【问题讨论】:
我已将其范围缩小到阵列控制器,该控制器将表格设置为自动重新排列内容。关闭时,不会发生错误,非常感谢任何有关如何解决此问题的提示... 【参考方案1】:结果证明这是一个错误。这是报告,以及原因和解决方法。
NSArrayController '自动重新排列内容' 引发 NSManagedObjects 的 KVO 异常
总结: 当在管理核心数据实体的数据的 NSArrayController 上检查“自动重新排列内容”时,会引发异常“无法删除键路径“x”的观察者”。
根据我的调查,似乎当在 NSArrayController 上检查“自动重新排列内容”时,KVO 合规性并未完全实现。在大多数情况下,它运行良好,但我发现有一个特定案例违反了这种合规性。
很难说清楚,但它似乎发生在尝试访问由 NSArrayController 管理并检查自动重新排列内容的实体的关系(即arrangedObjects.person.name)时。除此之外,它似乎只发生在重新打开文档之后并且该控制器正在管理一组恰好一个项目时......
如果您查看示例项目并按照以下步骤操作,可能会更容易...
重现步骤: 1)打开附加的项目 2) 打开 MyDocument.xib 3) 检查是否为 'Activity Persons' NSArrayController 检查了'Auto Rearrange Content' 4) 构建并运行 5) 通过单击左列下方的加号添加一个活动 6)通过单击右侧列下方的加号添加一个活动人员(不多也不少) 7) 保存文件 8) 重新打开文档
预期结果: 文档重新打开,用户可以通过响应式界面随意添加和删除活动和人员。
实际结果: 一旦右侧的列尝试显示只有一个 Activity Person 的 Activity 的 Activity Person,UI 就会出现不可预测的行为。使应用程序无法使用。
注意事项: 我创建了一个测试项目来定位这个错误,代码和模型应该是非常不言自明的,但如果有任何问题,请随时与我联系。
可以通过取消选中 Auto Rearrange Content 并手动调用 NSArrayController 上的arrangeObjects 来解决此问题。
【讨论】:
【参考方案2】:经过多次挠头和踩脚,我终于解决了这个问题。哇哦!
这个问题的原因实际上是我埋在我的一个表视图中的一个 NSNumberFormatter 实例。我应该更加注意从 Interface Builder 获得的控制台消息。
23/06/2009 15:05:08 ibtool[2324] -[NSConcreteAttributedString initWithString:] called with
nil string argument. This has undefined behavior and will raise an exception in post-
Leopard linked apps. This warning is displayed only once.
这实际上意味着我的 NSNumberFormatter 没有设置零符号和零符号(默认配置)。将这些都设置为零消除了上述错误,然后就像魔术一样,我再次符合 KVO。
我发现这可能会导致来自以下帖子的上述控制台消息: http://www.cocoabuilder.com/archive/message/cocoa/2009/5/28/237646
该消息确实让我担心,但由于它似乎不会影响我的应用程序并且是由“ibtool”(即不是我的应用程序)生成的,所以我最初选择忽略它。主要是因为我不知道在哪里可以找到发出警告的罪魁祸首。直到我用谷歌搜索控制台消息,我才能够解决它。我想我在 Cocoa 调试的世界里还有很多东西要学!
我仍然觉得奇怪的是,它只影响重新打开的文档,其中只有一个类别中的项目......
【讨论】:
不幸的是,这并不是罪魁祸首。似乎将我的阵列控制器设置为自动重新排列是问题所在。我仍在寻找解决办法...【参考方案3】:无法从
<NSManagedObject 0x16273380>
中删除键路径“item.name”的观察者<NSTableBinder 0x1627f670>
,这很可能是因为键“item”的值已更改而未发送适当的KVO 通知。检查 NSManagedObject 类的 KVO 兼容性。
这确实是最有可能的解释。您在未发布 KVO 通知的情况下更改了值。
你可能正在做这样的事情:
[item release];
item = [newItem retain];
这是错误的。直接实例变量赋值不会发布 KVO 通知,因此该语句不会告诉其他对象有关更改。
相反,您需要通过访问器。一种方法是显式访问器消息:
[self setItem:newItem];
另一种方式是属性赋值:
self.item = newItem;
它们是等价的并且给出完全相同的结果,包括 KVO 通知。
请注意,两个正确的解决方案都不包含retain
或copy
消息。这是您的 setter 访问器的工作(无论您是合成它,让 Core Data 动态创建它,还是自己编写它)。
always-use-accessors 规则的主要例外是您应该始终在init
方法和@987654332 中进行直接实例变量赋值(使用适当的release
和retain
/copy
消息) @ 方法。否则,您将向半初始化/解除锁定的对象发送消息。
【讨论】:
您好,感谢您的回复,但正如我的帖子中所述,我实际上使用的是核心数据的动态创建的设置器/访问器。这在所有其他时间都可以正常工作,除非重新打开一个类别中只有一个项目(不是零)的文档。以上是关于核心数据:重新打开文档时出现奇怪的绑定错误。帮助?的主要内容,如果未能解决你的问题,请参考以下文章
在 Java 对象的 Kotlin 中设置属性时出现奇怪的“无法重新分配 Val”错误