更新:此线程在集合视图的表示对象为NSManageBocts时标识NScollectionView中的错误。该错误触发如下;

(a)从NSarrayController(b)删除对象(b)在删除后的任何时间和NscollectionView完成动画之前的任何时候,在相关的NSMANAGEDOBJECTCONTEXT上删除对象。

Github上的这些项目证明了这个问题。

https://github.com/artifacts/nscollectionViewCoredataBughttps://github.com/iracooke/coredatacollectionviewcrashing

下面的原始问题

我有一个NscollectionView设置,其内容绑定与Core-Data实体的NSarrayController的布置结合。在我的收集项目视图(NscollectionView视图的原型)中,我有几个通过表示我的CollectionView项目绑定到Core-Data实体的控件。

在大多数情况下,这一切都可以。

当我尝试从ArrayController删除实体时,我会遇到OBJC_EXCEPTION。我只是通过打电话删除这些实体;

[myArrayController removeObject:managedObjectToDelete];

不幸的是,当我这样做时,我经常会得到“柯达塔无法实现的错误”错误。.负责任的实体是由NSarrayController管理的实体之一。

当抛出异常时,检查呼叫堆栈的检查表明,当NscollectionView收到其_EndoFanimation方法时,崩溃起源于此。反过来,这又启动了与解关的其他方法(在我看来,我的实体的属性可能具有控制属性)。

另一个信息是,我与我合作的实体与模型中的其他实体没有关系。

在我看来,以下问题正在发生。

  • 当我从nsarrayController中删除对象时,它们又从上下文中删除。
  • 从上下文删除后,对象变成故障
  • NscollectionView保留了对对象(现在故障)的引用。它试图在动画结束时清理它们(未连接等)。
  • 当NscollectionView试图清理对象绑定,它会导致核心数据试图在对象上发出故障(希望我将术语放在那里)。这会导致错误,因为该对象尚未保存到磁盘上。

我能想到的唯一方法是在删除之前(通过保存)将对象持续存在。这起作用,但仅以一种黑客的方式进行导致再次发生相同的错误。

这是否意味着我不能使用核心数据支持的NSArrayController来填充NscollectionView?如果不是,我做错了什么?在这个问题上有更好的方法吗?

有帮助吗?

解决方案

一个直接但无聊的答案:我可以确认核心数据支持的NSArrayController可以填充NscollectionView,在集合中,nsview项目中的不同GUI对象绑定到生成的“集合视图项目”,并指向路径沿路径的各种核心数据对象。编程删除NSArrayController作品的元素(并免费使用动画)。

也许您的收集视图中的某些绑定或其他依赖性引起了问题?还是托管对象上下文的线程问题?

其他提示

您可以通过在指向相应的ArrayController指向的CollectionItem中添加(分配)属性来解决此问题。

可以将此属性设置为 - [YournScollectionViewSubClass newitemwithRepresentedObject:]。

然后,您可以观察到每个项目中的布置对象。当它更改并进行项目时,不再包含在“布置”中包含的内容,您将项目设置为nil。在我的测试(10.6.8)中,这会触发Coredata之前的绑定清理,使对象变成故障。 (我的对象具有关系,项目视图中具有绑定)。

顺便说一句:此问题不仅限于在动画期间保存,撤消/重做/保存组合也可以触发它。

我一直在寻找一个很好的地方来开始观察物品,但是我想出的唯一一个是CopyWithzone:我想避免。 (-awakefromnib仅适用于第一项,-View为时过早)。

因此,我(勉强)决定在-newitemwithrepresentedObject中启动观察结果:并将其停在项目的-dealloc中。

您还应提防项目视图中对象触发的任何控件或其他操作 - 快速单击我可以导致消息交易对象,这大概是因为仍在反应按钮,该按钮在鼠标下进行动画。我的解决方案是在设置表示零时禁用控件。 YMMV。

这是我的观察者代码:

    - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if( object == self.arrayController && [keyPath isEqualToString: @"arrangedObjects"] ) {
        if( NO == [self.arrayController.arrangedObjects containsObject: self.representedObject] ) {
            self.representedObject = nil;

            for(NSView *subview in [self.view subviews]) {
                if( [subview isKindOfClass: [NSControl class]] ) {
                    [(NSControl *)subview setEnabled: NO];
                }
            }
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject: object change:change context:context];
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top