【问题标题】:How to bind a 1:many relation in Interface Builder如何在 Interface Builder 中绑定 1:many 关系
【发布时间】:2011-11-28 02:41:22
【问题描述】:

我有一个简单的 Core Data 应用程序,用于建模对象:员工和笔记。员工可以有很多笔记(1:many),每个笔记属于一个员工(1:1)。在员工窗口中,我使用 NSArrayController 显示存档的员工列表 (NSTableView)。点击员工会在列表旁边显示他们的详细信息(姓名地址、性别等)。现在,我还想显示所选员工的存档笔记列表(也是 NSTableView)。该列表应显示文件中每个注释的 2 个属性:其主题和条目日期)。

我尝试做以下事情:(1)绑定表的日期列到Employee控制器,控制器键:selection,模型键路径:notes.date(2)绑定Employee控制器的主题列,控制器key: selection, model key path: notes.topic

但是这会引发异常(无法识别的选择器)。

如何正确地将员工的 notes 属性绑定到 NSTableView?是否可以使用 IB 中的可可绑定“直接”完成,或者在我设置绑定之前访问员工的 notes 属性需要额外的代码吗?我检查了 Core Data 写入的数据,看起来一切正常。

非常感谢您的帮助...

编辑:这是来自调试器的堆栈跟踪...

2011-09-30 00:46:56.010 EmployeeDemo[3843:707] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[_NSFaultingMutableSet objectAtIndex:]: unrecognized selector sent to instance 0x10260b9c0'
*** First throw call stack: (
0   CoreFoundation                      0x00007fff8c654986 __exceptionPreprocess + 198
1   libobjc.A.dylib                     0x00007fff8b040d5e objc_exception_throw + 43
2   CoreFoundation                      0x00007fff8c6e05ae -[NSObject doesNotRecognizeSelector:] + 190
3   CoreFoundation                      0x00007fff8c641803 ___forwarding___ + 371
4   CoreFoundation                      0x00007fff8c641618 _CF_forwarding_prep_0 + 232
5   AppKit                              0x00007fff87c72648 -[NSTableBinder _visibleRowIndexesForObject:] + 267
6   AppKit                              0x00007fff87c72291 -[NSTableBinder observeValueForKeyPath:ofObject:change:context:] + 131
7   Foundation                          0x00007fff8dbb818a NSKeyValueNotifyObserver + 387
8   Foundation                          0x00007fff8dbb21af -[NSObject(NSKeyValueObservingPrivate) _notifyObserversForKeyPath:change:] + 756
9   AppKit                              0x00007fff876f1f0b -[NSController _notifyObserversForKeyPath:change:] + 206
10  AppKit                              0x00007fff877fc5fc -[NSController observeValueForKeyPath:ofObject:change:context:] + 847
11  AppKit                              0x00007fff879a1cf9 -[NSArrayController observeValueForKeyPath:ofObject:change:context:] + 98
12  Foundation                          0x00007fff8dbb818a NSKeyValueNotifyObserver + 387
13  Foundation                          0x00007fff8dbd9387 NSKeyValueDidChange + 486
14  Foundation                          0x00007fff8dc6834b -[NSObject(NSKeyValueObservingPrivate) _didChangeValuesForKeys:] + 631
15  CoreData                            0x00007fff8e827543 _PFFaultHandlerFulfillFault + 3619
16  CoreData                            0x00007fff8e825bd8 _PFFaultHandlerLookupRow + 1592
17  CoreData                            0x00007fff8e825254 _PF_FulfillDeferredFault + 212
18  CoreData                            0x00007fff8e8250d8 _sharedIMPL_pvfk_core + 56
19  CoreData                            0x00007fff8e85bd3e -[NSManagedObject valueForKey:] + 222
20  Foundation                          0x00007fff8dbb479e -[NSObject(NSKeyValueCoding) valueForKeyPath:] + 348
21  AppKit                              0x00007fff8799ded5 -[NSArrayController _multipleValueForKeyPath:atIndex:] + 84
22  AppKit                              0x00007fff8799cfc9 -[NSArrayController _singleValueForKeyPath:] + 151
23  AppKit                              0x00007fff87704cfe -[_NSControllerObjectProxy valueForKeyPath:] + 77
24  Foundation                          0x00007fff8dbb4761 -[NSObject(NSKeyValueCoding) valueForKeyPath:] + 287
25  AppKit                              0x00007fff87704baa -[NSBinder _valueForKeyPath:ofObject:mode:raisesForNotApplicableKeys:] + 654
26  AppKit                              0x00007fff87704894 -[NSBinder valueForBinding:resolveMarkersToPlaceholders:] + 171
27  AppKit                              0x00007fff87907352 -[NSValueBinder _referenceBindingValue] + 31
28  AppKit                              0x00007fff87907163 -[NSValueBinder _adjustObject:mode:observedController:observedKeyPath:context:editableState:adjustState:] + 647
29  AppKit                              0x00007fff87906e48 -[NSValueBinder _observeValueForKeyPath:ofObject:context:] + 303
30  AppKit                              0x00007fff8791ed0b -[NSTextValueBinder _observeValueForKeyPath:ofObject:context:] + 43
31  Foundation                          0x00007fff8dbb818a NSKeyValueNotifyObserver + 387
32  Foundation                          0x00007fff8dbb21af -[NSObject(NSKeyValueObservingPrivate) _notifyObserversForKeyPath:change:] + 756
33  AppKit                              0x00007fff876f1f0b -[NSController _notifyObserversForKeyPath:change:] + 206
34  AppKit                              0x00007fff8795e7a5 -[NSArrayController didChangeValuesForArrangedKeys:objectKeys:indexKeys:] + 120
35  AppKit                              0x00007fff879601bd -[NSArrayController setContent:] + 870
36  AppKit                              0x00007fff879a2664 -[NSArrayController(NSManagedController) _performFetchWithRequest:merge:error:] + 370
37  AppKit                              0x00007fff87bb149e -[NSObjectController(NSManagedController) fetchWithRequest:merge:error:] + 177
38  AppKit                              0x00007fff87bb1522 -[NSObjectController(NSManagedController) _executeFetch:didCommitSuccessfully:actionSender:] + 92
39  AppKit                              0x00007fff87d932e7 _NSSendCommitEditingSelector + 30
40  AppKit                              0x00007fff87a50246 -[NSController _controllerEditor:didCommit:contextInfo:] + 188
41  libdispatch.dylib                   0x00007fff847df90a _dispatch_call_block_and_release + 18
42  libdispatch.dylib                   0x00007fff847e177a _dispatch_main_queue_callback_4CF + 308
43  CoreFoundation                      0x00007fff8c5e9c0c __CFRunLoopRun + 1724
44  CoreFoundation                      0x00007fff8c5e9216 CFRunLoopRunSpecific + 230
45  HIToolbox                           0x00007fff871924ff RunCurrentEventLoopInMode + 277
46  HIToolbox                           0x00007fff87199c21 ReceiveNextEventCommon + 355
47  HIToolbox                           0x00007fff87199aae BlockUntilNextEventMatchingListInMode + 62
48  AppKit                              0x00007fff876de191 _DPSNextEvent + 659
49  AppKit                              0x00007fff876dda95 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135
50  AppKit                              0x00007fff876da3d6 -[NSApplication run] + 463
51  AppKit                              0x00007fff8795852a NSApplicationMain + 867
52  EmployeeDemo                        0x0000000100001a62 main + 34
53  EmployeeDemo                        0x0000000100001a34 start + 52
)
terminate called throwing an exception

编辑 2:

似乎还有一个与底层模型有关的问题。员工的备注是通过带有自己控制器的单独窗口输入的。它创建新注释并允许用户设置其属性(主题、正文)。当用户按下“保存”按钮时,会执行 saveNote 方法:

- (IBAction)saveNote:(id)sender {
[[self note] setValue: [[self topicField] stringValue] forKey: @"topic"];
[[self note] setValue: [[self textView] string] forKey: @"bodyText"];
[[self note] setValue: [self employee] forKey: @"employee"];
NSError *error = nil;
if (![[self managedObjectContext] save:&error]) {
            //todo: add proper error handling
    NSLog(@"An error occurred while trying to save the memo");
}
[[self window] close];

}

当我单步执行此方法时,实际上在设置便笺和员工之间的关系时会生成异常(第 3 行)。

【问题讨论】:

  • “无法识别的选择器”并不意味着“你刚才所做的一切都是错误的”;它的意思是“你所做的这个非常具体的事情是错误的”。消息的其余部分详细说明了具体内容。请编辑您的问题以包含它。
  • 我已将堆栈跟踪添加到问题中。我已经尝试了几个选项来让它工作 - 还尝试将 ArrayController 绑定到 notes 属性。这没有用。 notes 属性包含一个 NSSet 的实例,而 ArrayController 需要一个 NSArray。此外,正如您在评论中指出的那样,显然无法将表直接绑定到数组。
  • 从堆栈跟踪中,我猜您正在将一个数组控制器绑定到一个 NSSet 属性(IIRC,这就是 Core Data 中的多对多关系)。确保绑定它的contentSet,而不是它的contentArray
  • 好的,谢谢。当我设置新笔记和员工之间的关系时,似乎还有另一个问题潜伏着,这显然会导致异常......(我在一个问题中提出一个问题......不太确定这是否是正确的网站礼仪。如果不是,请道歉)
  • 是否是同一个异常,具有相同的堆栈跟踪?如果是,那么您可能已经取得了进展,但这个问题中的问题仍未解决。如果不是,那应该是一个新问题。

标签: xcode cocoa xcode4 cocoa-bindings


【解决方案1】:

你需要的是一个 NSArrayController ,它的内容绑定到关系上。然后将 NSTableView 内容绑定到 NSArrayController。从那里你可以做列。

更新

这个tutorial from Apple 可能会帮助你。

【讨论】:

  • 您不绑定表格视图的内容。绑定列时会自动绑定。自己绑定表格视图的内容会导致问题。
  • 感谢教程的链接。这很有帮助!
  • 是的!感谢您的教程!
【解决方案2】:

我的问题中描述的行为似乎与拥有基于文档的 Core Date 应用程序或拥有“普通”核心数据应用程序(您在 XCode 中创建新项目时进行的检查)有关。

我发现当我选择基于文档的核心数据应用时,并没有出现上述问题。当我开发与非文档核心数据应用程序相同的应用程序时,绑定注释控制器会生成堆栈跟踪,如我原来的问题所示,并且在我向现有员工添加注释时立即引发异常。

所以,平心而论,这只是解决方案的一部分,因为我对 Cocoa 和 XCode 的经验不足以解释为什么它不能使用基于非文档的变体。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2010-12-21
    • 1970-01-01
    • 2017-05-20
    • 1970-01-01
    相关资源
    最近更新 更多