如何使用NSArrayController绑定存储和恢复NSTableView选择?

时间:2016-03-09 10:50:42

标签: core-data selection nstableview cocoa-bindings

我使用两个CoreData实体,两个NSTableView和两个NSArrayController创建了一个简单的主详细信息应用程序,通过绑定而不是编写代码来连接所有内容。我想记住并恢复每个主行的选定详细信息行。

主实体有标题和多个细节(一对多关系):

class Master: NSManagedObject {
}

// Generated
extension Master {
    @NSManaged var title: String?
    @NSManaged var details: NSSet?
}

详情实体只有一个标题:

class Detail: NSManagedObject {
}

// Generated
extension Master {
    @NSManaged var title: String?
}

第一个表视图显示所有主实体,第二个表视图显示第一个表中所选主实体的所有详细信息实体。两个表视图都配置为仅允许单个选择:

Simple master detail application

我现在想要做的是在主实体中存储所选细节的索引。当再次选择相同的主实体时,第二个表视图应自动恢复该选择并再次选择相同的细节。

为了方便起见,我在selectionIndexes: NSIndexSet实体中添加了一个简单的Master属性。然后我将此属性绑定到NSArrayController的选择索引属性的详细信息:

Binding selection indexes

拥有此选择索引绑定实际上存储了所选的详细信息索引,但是当再次选择相同的主实体时,某些Cocoa代码会将选择重置为空。这表示存储的选择被空选择覆盖。

Avoid Empty SelectionPreserve Selection是禁用的,以避免NSArrayController在没有选择项目的情况下自动选择项目,或者在内容发生变化时始终尝试再次选择相同项目(这不是我想要的因为不同主实体可能具有相同标题的详细信息。)

我已查看getsetselectionIndexes媒体资源的调用,例如:

class Master: NSManagedObject {

    var _selection = NSMutableIndexSet()
    var selectionIndexes: NSIndexSet {
        get {
            print("get", _selection)
            return _selection
        }
        set(selection) {
            _selection.removeAllIndexes()
            _selection.addIndexes(selection)
            print("set", _selection)
            //print(NSThread.callStackSymbols())
        }
    }
}

这是通话记录:

选择第一个主实体的第三个细节:

set [number of indexes: 1 (in 1 ranges), indexes: (2)]
get [number of indexes: 1 (in 1 ranges), indexes: (2)]

选择其他主要实体:

get (no indexes)

然后再次选择第一个主实体:

get [number of indexes: 1 (in 1 ranges), indexes: (2)]
set (no indexes)
get (no indexes)

如您所见,它首先恢复索引2(第3个详细信息实体),然后分配(no indexes)。为什么此时会重新分配selectionIndexes?这是最后一次set调用的调用堆栈:

"0   SelectionTest                       0x00000001000029fd _TFC13SelectionTest6Masters16selectionIndexesCSo10NSIndexSet + 797",
"1   SelectionTest                       0x00000001000026ca _TToFC13SelectionTest6Masters16selectionIndexesCSo10NSIndexSet + 58",
"2   Foundation                          0x00007fff9d2a6c13 _NSSetObjectValueAndNotify + 148",
"3   AppKit                              0x00007fff9c9f09ae -[NSArrayController _setMultipleValue:forKeyPath:atIndex:] + 208",
"4   Foundation                          0x00007fff9d25d80f -[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 287",
"5   AppKit                              0x00007fff9c88a72e -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 411",
"6   AppKit                              0x00007fff9c88a53c -[NSBinder setValue:forBinding:error:] + 248",
"7   AppKit                              0x00007fff9ca958c3 -[NSControllerConfigurationBinder _updateSelectionIndexes:] + 226",
"8   AppKit                              0x00007fff9ca95ab0 -[NSControllerConfigurationBinder _observeValueForKeyPath:ofObject:context:] + 111",
"9   Foundation                          0x00007fff9d255a53 NSKeyValueNotifyObserver + 379",
"10  Foundation                          0x00007fff9d25fd7a -[NSObject(NSKeyValueObservingPrivate) _notifyObserversForKeyPath:change:] + 1127",
"11  AppKit                              0x00007fff9c6e57d8 -[NSController _notifyObserversForKeyPath:change:] + 206",
"12  AppKit                              0x00007fff9c74242b -[NSArrayController didChangeValuesForArrangedKeys:objectKeys:indexKeys:] + 126",
"13  AppKit                              0x00007fff9c74208f -[NSArrayController _selectObjectsAtIndexesNoCopy:avoidsEmptySelection:sendObserverNotifications:forceUpdate:] + 584",
"14  Foundation                          0x00007fff9d23c178 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 424",
"15  AppKit                              0x00007fff9c88a72e -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 411",
"16  AppKit                              0x00007fff9c88a53c -[NSBinder setValue:forBinding:error:] + 248",
"17  AppKit                              0x00007fff9c868931 -[NSTableBinder tableView:didChangeToSelectedRowIndexes:] + 138",
"18  AppKit                              0x00007fff9c868857 -[_NSBindingAdaptor tableView:didChangeToSelectedRowIndexes:] + 153",
"19  AppKit                              0x00007fff9c728504 -[NSTableView _sendSelectionChangedNotificationForRows:columns:] + 119",
"20  AppKit                              0x00007fff9c6f9723 -[NSTableView _enableSelectionPostingAndPost] + 424",
"21  AppKit                              0x00007fff9c881a15 -[NSTableView mouseDown:] + 5358",
"22  AppKit                              0x00007fff9cd83d1d -[NSWindow _handleMouseDownEvent:isDelayedEvent:] + 6322",
"23  AppKit                              0x00007fff9cd84fad -[NSWindow _reallySendEvent:isDelayedEvent:] + 212",
"24  AppKit                              0x00007fff9c6dd735 -[NSWindow sendEvent:] + 517",
"25  AppKit                              0x00007fff9c6d9e49 -[NSApplication sendEvent:] + 2540",
"26  AppKit                              0x00007fff9c60d03a -[NSApplication run] + 796",
"27  AppKit                              0x00007fff9c58f520 NSApplicationMain + 1176",
"28  SelectionTest                       0x0000000100004d07 main + 87",
"29  libdyld.dylib                       0x00007fff892705ad start + 1",
"30  ???                                 0x0000000000000003 0x0 + 3"

现在显而易见的问题是:如何让NSArrayController存储并将选定的详细信息索引恢复到其主实体中,而不会让其他人覆盖它?

0 个答案:

没有答案