在 Foundation 框架中,SortDescriptor
(或 NSSortDescriptor
)用于定义集合数据的排序规则,支持对属性键路径、排序顺序及自定义比较逻辑的控制。以下是详细使用方法和多场景示例:
1. 基本概念 #
- 作用:定义排序规则,用于对数组、Core Data/SwiftData 查询结果等集合进行排序。
- 核心属性:
keyPath
:排序依据的属性路径(如\User.name
)。ascending
:是否升序(默认true
)。comparator
:自定义比较逻辑(可选)。
2. 基础用法 #
Swift 示例(SwiftData) #
// 按 name 升序排序
let descriptor = SortDescriptor<User>(\.name)
// 按 company.name 降序排序
let descriptor = SortDescriptor<User>(\.company.name, order: .reverse)
// 多条件排序:先按 company.name 升序,再按 name 降序
let descriptors = [
SortDescriptor<User>(\.company.name),
SortDescriptor<User>(\.name, order: .reverse)
]
Objective-C 示例(NSSortDescriptor) #
// 按 name 升序排序
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
// 多条件排序:先按 company.name 升序,再按 name 降序
NSArray *descriptors = @[
[NSSortDescriptor sortDescriptorWithKey:@"company.name" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO]
];
3. 使用场景与示例 #
场景 1:SwiftData 查询排序 #
// 查询 User 并按 name 排序
let descriptor = FetchDescriptor<User>(sortBy: [SortDescriptor(\.name)])
let users = try context.fetch(descriptor)
场景 2:对 Swift 数组排序 #
let users = [User(name: "张三"), User(name: "李四")]
let sortedUsers = users.sorted(using: [SortDescriptor(\.name, order: .reverse)])
场景 3:自定义比较逻辑 #
// 按字符串长度排序
let descriptor = SortDescriptor<String> { $0.count < $1.count }
let strings = ["Swift", "Foundation", "iOS"]
let sortedStrings = strings.sorted(using: [descriptor]) // ["iOS", "Swift", "Foundation"]
场景 4:多条件混合排序 #
// 先按 company.address 升序,再按 name 降序
let descriptors = [
SortDescriptor(\.company.address),
SortDescriptor(\.name, order: .reverse)
]
let sortedUsers = users.sorted(using: descriptors)
4. 与其他框架结合 #
Core Data 查询 #
// 使用 NSSortDescriptor(Objective-C 兼容)
let request: NSFetchRequest<User> = User.fetchRequest()
request.sortDescriptors = [
NSSortDescriptor(key: "name", ascending: true)
]
Combine 流处理 #
// 对发布的数据流排序
usersPublisher
.map { users in
users.sorted(using: [SortDescriptor(\.name)])
}
.sink { print($0) }
5. 注意事项 #
- 性能:对大数据集排序时,优先使用索引属性(如
@Attribute(.unique)
标注的字段)。 - 兼容性:
SortDescriptor
在 Swift 和 Objective-C 中行为一致,但 Swift 版本支持更简洁的语法。 - 自定义逻辑:复杂排序可通过闭包实现,但需注意闭包捕获上下文的开销。
完整示例代码 #
SwiftData 多条件排序 #
struct ContentView: View {
@Query(sort: [
SortDescriptor(\User.company.name),
SortDescriptor(\User.name, order: .reverse)
]) var users: [User]
var body: some View {
List(users) { user in
Text(user.name)
}
}
}
Objective-C 多字段排序 #
NSArray *users = @[user1, user2, user3];
NSArray *sortedUsers = [users sortedArrayUsingDescriptors:@[
[NSSortDescriptor sortDescriptorWithKey:@"company.address" ascending:YES],
[NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO]
]];
通过上述示例,可灵活应用 SortDescriptor
实现单字段、多字段、自定义逻辑的排序需求。