【发布时间】:2016-07-01 17:50:44
【问题描述】:
给定一个NSTableView,它有一个结构数组作为其数据源。用户可以单击任何列标题以按该列排序。列标识符与结构中属性的属性名称匹配。
给定一个结构
struct MyStructure {
var col0data = "" //name matches the column identifier
var col1data = ""
}
还有一个结构数组
var myArray = [MyStructure]()
目标是当单击列标题时,使用该列的标识符按该列标识符/属性对结构数组进行排序
有了字典数组,这很容易......
self.myArrayOfDictionaries.sortInPlace {
(dictOne, dictTwo) -> Bool in
let d1 = dictOne[colIdentifier]! as String;
let d2 = dictTwo[colIdentifier]! as String;
return d1 < d2 //or return d1 > d2 for reverse sort
}
问题是如何动态访问结构的属性,比如
let struct = myArray[10] as! MyStructure //get the 10th structure in the array
let value = struct["col0data"] as! String //get the value of the col0data property
如果有更好的方法,不胜感激。
我还应该注意,该结构可能有 50 个属性,因此这是为了减少按这些属性中的任何一个对数组进行排序所需的代码量。
编辑:
一种解决方案是将结构更改为从 NSObject 派生的类。然后可以通过 .valueForKey("some key") 访问属性。但是,我正在努力保持这种 Swifty。
【问题讨论】:
-
你为什么在这里使用结构体?对于 50 个属性,数组或字典似乎是更合适的选择。如果您需要封装额外的逻辑,那么您可以将数组或字典作为结构的属性。
-
@originaluser2 我从一个字典数组开始,它非常适合排序等。但是,随着项目的发展,我需要添加对象逻辑,从而转移到结构或类。无论哪种方式,它们仍然需要通过从 tableView 标题单击派生的属性之一进行排序。我可以用一堆 if..then 语句强制它(如果 headerClick = "col0" 然后按 x 排序,如果 headerClick = "col1" 按 y 排序等),但这似乎很不雅。
-
那么为什么不简单地将字典作为结构的属性呢?这样,您既可以封装又可以轻松查找值。
-
@originaluser2 这是一个结构数组,用作 tableView 的数据源。因此,它们(结构)需要通过其中一个属性(与单击的列的标题匹配的那个)进行排序。如果字典嵌入在结构中,则无法对结构数组进行排序。但是,如果有办法,这是一个很好的解决方案,所以将其发布为答案!
-
使用
NSArrayController和 Cocoa 绑定,然后您就可以免费获得一切。但这需要一个类而不是一个结构作为模型。