Cocoa 绑定 - 特定列的排序错误
Cocoa bindings - Sorting error for a specific column
我使用绑定到 NSTreeController 的 NSOutlineView。
我成功地对视图的所有列进行了排序,除了一列!
此列显示一个按钮,如果 binaryData
字段不为零,则该按钮已启用。
模型中的 binaryData
字段是与 MyBinary
NSManagedObject 子类的关系,后者具有 NSData?
字段。我按照推荐使用这种方法(一种关系)以避免在不需要时将所有 NSData 加载到内存中。
我希望此列可排序,并且在单击时重新组合所有启用的按钮(升序或降序),并重新组合所有禁用的按钮。
在 IB 中,与其他列一样,我将列值绑定到:
- 控制器键 = arrangedObjects
- 模型关键路径 = binaryData
但是当我点击该列时,我有以下堆栈:
2019-11-09 10:31:44.713177+0100 MyApp[71910:2872832] -[MyApp.MyBinary compare:]: unrecognized selector sent to instance 0x6000021429e0
2019-11-09 10:31:44.713628+0100 MyApp[71910:2872832] [General] -[MyApp.MyBinary compare:]: unrecognized selector sent to instance 0x6000021429e0
2019-11-09 10:31:44.717803+0100 MyApp[71910:2872832] [General] (
0 CoreFoundation 0x00007fff36294f53 __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff6c35a835 objc_exception_throw + 48
2 CoreFoundation 0x00007fff3631f106 -[NSObject(NSObject) __retain_OA] + 0
3 CoreFoundation 0x00007fff3623b6cb ___forwarding___ + 1427
4 CoreFoundation 0x00007fff3623b0a8 _CF_forwarding_prep_0 + 120
5 Foundation 0x00007fff388a1a44 _NSCompareObject + 46
6 CoreFoundation 0x00007fff36206288 __CFSimpleMergeSort + 74
7 CoreFoundation 0x00007fff362061a6 CFSortIndexes + 390
8 CoreFoundation 0x00007fff36223720 CFMergeSortArray + 290
9 Foundation 0x00007fff388a179b _sortedObjectsUsingDescriptors + 592
10 Foundation 0x00007fff388a1397 -[NSArray(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 317
11 AppKit 0x00007fff33666373 -[NSTreeNode sortWithSortDescriptors:recursively:] + 461
12 AppKit 0x00007fff336664be -[NSTreeNode sortWithSortDescriptors:recursively:] + 792
13 AppKit 0x00007fff33666073 -[NSTreeController setSortDescriptors:] + 304
14 Foundation 0x00007fff388e1ce3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 363
15 AppKit 0x00007fff336695bb -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 445
16 AppKit 0x00007fff336693aa -[NSBinder setValue:forBinding:error:] + 236
17 AppKit 0x00007fff33ab0359 -[NSOutlineViewBinder tableView:didChangeToSortDescriptors:] + 119
18 AppKit 0x00007fff337c10cc -[_NSBindingAdaptor tableView:didChangeToSortDescriptors:] + 152
19 AppKit 0x00007fff3366bba8 -[NSTableView setSortDescriptors:] + 258
20 AppKit 0x00007fff33ba44e8 -[NSTableView _changeSortDescriptorsForClickOnColumn:] + 536
21 AppKit 0x00007fff33b8a127 -[NSTableHeaderView _trackAndModifySelectionWithEvent:onColumn:stopOnReorderGesture:] + 999
22 AppKit 0x00007fff33b8d24a -[NSTableHeaderView mouseDown:] + 546
23 AppKit 0x00007fff335f25e9 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4907
24 AppKit 0x00007fff33535eb0 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2612
25 AppKit 0x00007fff3353523d -[NSWindow(NSEventRouting) sendEvent:] + 349
26 AppKit 0x00007fff333f945c -[NSApplication(NSEvent) sendEvent:] + 352
27 AppKit 0x00007fff333e8da7 -[NSApplication run] + 707
28 AppKit 0x00007fff333da95d NSApplicationMain + 777
29 MyApp 0x000000010002b02d main + 13
30 libdyld.dylib 0x00007fff6d6bd2e5 start + 1
31 ??? 0x0000000000000003 0x0 + 3
)
我该如何解决这个问题?我想过使用自定义排序描述符,但我不知道如何告诉 OutlineView 或 TreeController 为特定列使用特定描述符。
感谢您的帮助!
how to tell the OutlineView or the TreeController to use a specific descriptor for a specific column
设置table列的sortDescriptorPrototype。
好的,找到了。
第一步是使用 NSTableColumn.sortDescriptorPrototype
在列上设置自定义 NSSortDescriptor
。
要创建 NSSortDescriptor,您可以使用:
init(key: String?, ascending: Bool, comparator: Comparator)
要么
init(key: String?, ascending: Bool, selector: Selector?)
这会给比较器:
column.sortDescriptorPrototype = NSSortDescriptor(key: "myBindingKeyPath", ascending: true, comparator: { (obj1, obj2) -> ComparisonResult in
// .... your logic
return .orderedSame
})
对于选择器:
Column.sortDescriptorPrototype = NSSortDescriptor(key: "myBindingKeyPath", ascending: true, selector: #selector(MyBinary.compare(_:)))
}
和 MyBinary class 中的比较函数将通过选择器访问:
@objc
public func compare(_ other: PDFBinary) -> ComparisonResult {
return .orderedSame
}
第二个解决方案解决了我的问题,因为我使用的是 autosaveTableColumns
属性,这会导致第一个解决方案出现问题。
我使用绑定到 NSTreeController 的 NSOutlineView。
我成功地对视图的所有列进行了排序,除了一列!
此列显示一个按钮,如果 binaryData
字段不为零,则该按钮已启用。
模型中的 binaryData
字段是与 MyBinary
NSManagedObject 子类的关系,后者具有 NSData?
字段。我按照推荐使用这种方法(一种关系)以避免在不需要时将所有 NSData 加载到内存中。
我希望此列可排序,并且在单击时重新组合所有启用的按钮(升序或降序),并重新组合所有禁用的按钮。
在 IB 中,与其他列一样,我将列值绑定到:
- 控制器键 = arrangedObjects
- 模型关键路径 = binaryData
但是当我点击该列时,我有以下堆栈:
2019-11-09 10:31:44.713177+0100 MyApp[71910:2872832] -[MyApp.MyBinary compare:]: unrecognized selector sent to instance 0x6000021429e0
2019-11-09 10:31:44.713628+0100 MyApp[71910:2872832] [General] -[MyApp.MyBinary compare:]: unrecognized selector sent to instance 0x6000021429e0
2019-11-09 10:31:44.717803+0100 MyApp[71910:2872832] [General] (
0 CoreFoundation 0x00007fff36294f53 __exceptionPreprocess + 250
1 libobjc.A.dylib 0x00007fff6c35a835 objc_exception_throw + 48
2 CoreFoundation 0x00007fff3631f106 -[NSObject(NSObject) __retain_OA] + 0
3 CoreFoundation 0x00007fff3623b6cb ___forwarding___ + 1427
4 CoreFoundation 0x00007fff3623b0a8 _CF_forwarding_prep_0 + 120
5 Foundation 0x00007fff388a1a44 _NSCompareObject + 46
6 CoreFoundation 0x00007fff36206288 __CFSimpleMergeSort + 74
7 CoreFoundation 0x00007fff362061a6 CFSortIndexes + 390
8 CoreFoundation 0x00007fff36223720 CFMergeSortArray + 290
9 Foundation 0x00007fff388a179b _sortedObjectsUsingDescriptors + 592
10 Foundation 0x00007fff388a1397 -[NSArray(NSKeyValueSorting) sortedArrayUsingDescriptors:] + 317
11 AppKit 0x00007fff33666373 -[NSTreeNode sortWithSortDescriptors:recursively:] + 461
12 AppKit 0x00007fff336664be -[NSTreeNode sortWithSortDescriptors:recursively:] + 792
13 AppKit 0x00007fff33666073 -[NSTreeController setSortDescriptors:] + 304
14 Foundation 0x00007fff388e1ce3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 363
15 AppKit 0x00007fff336695bb -[NSBinder _setValue:forKeyPath:ofObject:mode:validateImmediately:raisesForNotApplicableKeys:error:] + 445
16 AppKit 0x00007fff336693aa -[NSBinder setValue:forBinding:error:] + 236
17 AppKit 0x00007fff33ab0359 -[NSOutlineViewBinder tableView:didChangeToSortDescriptors:] + 119
18 AppKit 0x00007fff337c10cc -[_NSBindingAdaptor tableView:didChangeToSortDescriptors:] + 152
19 AppKit 0x00007fff3366bba8 -[NSTableView setSortDescriptors:] + 258
20 AppKit 0x00007fff33ba44e8 -[NSTableView _changeSortDescriptorsForClickOnColumn:] + 536
21 AppKit 0x00007fff33b8a127 -[NSTableHeaderView _trackAndModifySelectionWithEvent:onColumn:stopOnReorderGesture:] + 999
22 AppKit 0x00007fff33b8d24a -[NSTableHeaderView mouseDown:] + 546
23 AppKit 0x00007fff335f25e9 -[NSWindow(NSEventRouting) _handleMouseDownEvent:isDelayedEvent:] + 4907
24 AppKit 0x00007fff33535eb0 -[NSWindow(NSEventRouting) _reallySendEvent:isDelayedEvent:] + 2612
25 AppKit 0x00007fff3353523d -[NSWindow(NSEventRouting) sendEvent:] + 349
26 AppKit 0x00007fff333f945c -[NSApplication(NSEvent) sendEvent:] + 352
27 AppKit 0x00007fff333e8da7 -[NSApplication run] + 707
28 AppKit 0x00007fff333da95d NSApplicationMain + 777
29 MyApp 0x000000010002b02d main + 13
30 libdyld.dylib 0x00007fff6d6bd2e5 start + 1
31 ??? 0x0000000000000003 0x0 + 3
)
我该如何解决这个问题?我想过使用自定义排序描述符,但我不知道如何告诉 OutlineView 或 TreeController 为特定列使用特定描述符。
感谢您的帮助!
how to tell the OutlineView or the TreeController to use a specific descriptor for a specific column
设置table列的sortDescriptorPrototype。
好的,找到了。
第一步是使用 NSTableColumn.sortDescriptorPrototype
在列上设置自定义 NSSortDescriptor
。
要创建 NSSortDescriptor,您可以使用:
init(key: String?, ascending: Bool, comparator: Comparator)
要么
init(key: String?, ascending: Bool, selector: Selector?)
这会给比较器:
column.sortDescriptorPrototype = NSSortDescriptor(key: "myBindingKeyPath", ascending: true, comparator: { (obj1, obj2) -> ComparisonResult in
// .... your logic
return .orderedSame
})
对于选择器:
Column.sortDescriptorPrototype = NSSortDescriptor(key: "myBindingKeyPath", ascending: true, selector: #selector(MyBinary.compare(_:)))
}
和 MyBinary class 中的比较函数将通过选择器访问:
@objc
public func compare(_ other: PDFBinary) -> ComparisonResult {
return .orderedSame
}
第二个解决方案解决了我的问题,因为我使用的是 autosaveTableColumns
属性,这会导致第一个解决方案出现问题。