这里有几个问题需要解决:
对多维数组进行排序
为了测试,我resultsArray
用一些虚假的行填写了你的格式:
let resultsArray = [
["10-24-2015", "124", "Yes", "No", "No", "Yes", "Yes", "NA", "NA"],
["09-23-2015", "125", "Yes", "No", "No", "No", "Yes", "NA", "NA"],
["10-21-2015", "121", "Yes", "No", "Yes", "Yes", "Yes", "NA", "NA"],
["08-24-2015", "141", "Yes", "Yes", "No", "Yes", "Yes", "NA", "NA"],
["10-24-2014", "199", "Yes", "No", "No", "Yes", "No", "NA", "NA"],
]
现在,在 Swift 中对它进行排序非常简单:调用sort
函数,并传递一个闭包,该闭包接受两个(外部)数组元素,true
如果第一个应该在第二个之前排序,则返回。你的元素是类型的[String]
——即字符串数组——所以要按子数组元素之一排序,你只需要查找它们并比较它们。
let sorted = resultsArray.sort { left, right in
left[0] < right[0]
}
// or a shorter syntax:
let sorted2 = resultsArray.sort { $0[0] < $1[0] }
但这可能不是你想要的。
按日期排序
上面按字典顺序对字符串进行排序。这意味着您会得到如下结果:
["08-24-2015", "141", "Yes", "Yes", "No", "Yes", "Yes", "NA", "NA"]
["09-23-2015", "125", "Yes", "No", "No", "No", "Yes", "NA", "NA"]
["10-21-2015", "121", "Yes", "No", "Yes", "Yes", "Yes", "NA", "NA"]
["10-24-2014", "199", "Yes", "No", "No", "Yes", "No", "NA", "NA"]
["10-24-2015", "124", "Yes", "No", "No", "Yes", "Yes", "NA", "NA"]
您的日期格式是月-日-年,因此当您将这些作为字符串进行比较时,您不会得到时间顺序(“08-24-2015”在“10-24-2014”之前,因为第一个以“08”开头”)。
更好的方法是解析日期,以便您可以将它们作为日期进行比较。这是一个镜头:
// parse actual dates
let formatter = NSDateFormatter()
formatter.dateFormat = "MM-dd-yyyy"
let sorted3 = resultsArray.sort { left, right in
let leftDate = formatter.dateFromString(left[0])!
let rightDate = formatter.dateFromString(right[0])!
// NSDate doesn't have a < operator, so use the Foundation compare method
return leftDate.compare(rightDate) == .OrderedAscending
}
这按您期望的方式排序。不过,你可能会变得更好。
使用模型对象
您可能希望对这些进行更多操作,因此将行视为每个字段都具有某些含义的对象可能会有所帮助。例如:
struct Result {
let date: NSDate
let number: Int
let responses: [Bool?]
init(array: [String]) {
date = formatter.dateFromString(array[0])!
number = Int(array[1])!
responses = array[2..<array.count].map {
switch $0 {
case "Yes": return true
case "No": return false
default: return nil
}
}
}
}
现在您可以为每个结果拥有真实的对象,这样您就可以更好地跟踪您以后的代码中的内容。让我们创建一个Result
对象数组,并对其进行排序:
let results = resultsArray.map(Result.init).sort {
$0.date.compare($1.date) == .OrderedAscending
}
等等,我们这样做了多少次?
您正在方法中完成所有数据加载和排序(以及日期解析和转换为Result
对象,如果您遵循我上面的建议)tableView(_:cellForRowAtIndexPath:)
。对于表中的每一行,都会调用一次此方法……这可能是由于您还在该tableView(_:numberOfRowsInSection:)
方法中加载了数据,这是数据文件中的结果数。这意味着您一次又一次地做同样的工作,并减慢表的初始加载速度(以及任何后续的重新加载,以及行缓存溢出时的滚动)。
将数据加载、解析和排序代码移动到只执行一次的地方(或者每次更改底层数据文件并希望重新加载其更新内容时执行一次)。也许viewDidLoad
,也许是您可以稍后再次调用的实用方法。让它将结果保存在表视图控制器的实例属性中。然后,您可以在需要时更快地参考这些结果。
例如(用一些伪代码缩短):
class MyTableViewController: UITableViewController {
let cellIdentifier = "resultsViewCell"
var results: [Result]!
override func viewDidLoad() {
let resultsdocumentsURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)[0]
let resultsfileURL = resultsdocumentsURL.URLByAppendingPathComponent("ResultsPlist.plist")
guard let resultsArray = NSKeyedUnarchiver.unarchiveObjectWithFile(resultsfileURL.path!) as? [[String]]
else { fatalError("unexpected results from plist") }
results = resultsArray.map(Result.init).sort {
$0.date.compare($1.date) == .OrderedAscending
}
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return results.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ResultsTableViewCell
let result = results[indexPath.row]
cell.textLabel?.text = result.description // or however you display a result
}
}