2015-05-31 125 views
6

我正在使用iOS应用程序,并且我已将数据存储在CoreData中,并将其加载到UITableView中。数据实体具有称为id的属性,该属性是包含A后跟数字(即“A1”“A2”等)的字符串。Swift中的NSSortDescriptor

当我使用此代码为排序,我结束与表被字典顺序排序(即, “A1”, “A10”, “A11”, “A12”, “A2”, “A3” 等)

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true) 
fetchRequest.sortDescriptors = [sortDescriptor] 

正如你所期望的,我真正想要的是对它进行数字排序。我如何去做这件事?我知道一个NSComparator可以作为参数添加到NSSortDescriptor,但我不能为我的生活得到它的想法。预先感谢任何帮助!

回答

10

基于(基于SQLite的)核心数据获取请求中的排序描述符不能使用自定义比较器,只能使用有限的“内置”比较方法 方法。这在 Fetch Predicates and Sort Descriptors“核心数据编程指南”中介绍:

...的SQL存储,而另一方面,编译谓词和排序 描述符SQL和评估结果在数据库本身。 这主要是为了性能,但这意味着评估 发生在非Cocoa环境中,因此依赖Cocoa的排序描述符(或 谓词)无法工作。支持的排序 选择是compare:caseInsensitiveCompare:localizedCompare:localizedCaseInsensitiveCompare:,并且localizedStandardCompare:(该 后者是搜索类排序,和大多数人应该用得最多的 的时间)。另外,您无法使用SQLite存储区使用 对瞬态属性进行排序。

幸运的是,有一个应该满足您的需求:

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true, 
         selector: "localizedStandardCompare:") 

localizedStandardCompare:做了“查找类似”特别对待数字的字符串中根据自己的 数值比较 。

对于Swift 2.2/Xcode 7。3及更高版本:

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true 
         selector: #selector(NSString.localizedStandardCompare)) 
+0

正是我需要的。谢谢! –

+0

新格式似乎是.. NSSortDescriptor(关键: “ID”,上升:真,选择:#selector(NSString.localizedCompare(_ :))) –

+0

@JosephAstrahan:谢谢,更新! –

1

的SWIFTY方式:

var arr = ["A1", "A10", "A11", "A12", "A2", "A3"] 
arr.sort {dropFirst($0).toInt() < dropFirst($1).toInt()} 

所以,你可以直接使用,或者用它作为你比较块的基础。如果你坚持在有效的Objective-C中这样做,你可以使用NSString compare:options:,其中options:包括NSNumericSearch

+2

这样的工作排序的数据* *后获取他们,但不是那种描述符核心数据读取请求。 –

0

斯威夫特3

let sortDescriptor = NSSortDescriptor(key: "id", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare))

希望它有助于

0

对于Swift3

关键是

result: Bool = 0 < "string1".localizedCompare("string2").rawValue 

使用这样

[some string array].sorted { return 0 < "string1".localizedCompare("string2").rawValue } 
0

为什么用OBJ-C风格的NSSortDescriptor打扰,在急速的,我们可以很好地使用排序斯威夫特高阶函数 - Xcode的8.x的迅速3.X

class Person: NSObject { 
    let firstName: String 
    let lastName: String 
    let age: Int 

    init(firstName: String, lastName: String, age: Int) { 
     self.firstName = firstName 
     self.lastName = lastName 
     self.age = age 
    } 
    override var description: String { 
     return "\(firstName) \(lastName)" 
    } 
} 

let a = Person(firstName: "a", lastName: "b", age: 24) 
let b = Person(firstName: "c", lastName: "d", age: 27) 
let c = Person(firstName: "e", lastName: "f", age: 33) 
let d = Person(firstName: "g", lastName: "h", age: 31) 
let peopleObject = [d, b, a, c] 
//SWIFTY 
let sortedByFirstNameSwifty = peopleObject.sorted(by: { $0.firstName < $1.firstName }) 
print(sortedByFirstNameSwifty)//prints[a b, c d, e f, g h] 


//Objective c way 
let firstNameSortDescriptor = NSSortDescriptor(key: "firstName", ascending: true, selector: #selector(NSString.localizedStandardCompare(_:))) 
let sortedByFirstName = (peopleObject as NSArray).sortedArray(using: [firstNameSortDescriptor]) 
print(sortedByFirstName)//prints [a b, c d, e f, g h]