Filter and Sorting — SortDescriptor

在 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. 注意事项 #

  1. 性能:对大数据集排序时,优先使用索引属性(如 @Attribute(.unique) 标注的字段)。
  2. 兼容性SortDescriptor 在 Swift 和 Objective-C 中行为一致,但 Swift 版本支持更简洁的语法。
  3. 自定义逻辑:复杂排序可通过闭包实现,但需注意闭包捕获上下文的开销。

完整示例代码 #

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 实现单字段、多字段、自定义逻辑的排序需求。

本文共 829 字,创建于 Feb 22, 2025
相关标签: Xcode, Foundation