Swift 中的 KeyPath

简介: Swift 中的 反斜杠点 (\.xxx)到底是个啥

Swift 中的 KeyPath

当在Swift中进行编程时,Keypath(键路径)是一个强大的特性,用于引用对象的属性,从而实现更加灵活和类型安全的代码。让我们通过一个实际案例详细解析Keypath的使用。

// 1
struct User {
    
   let name: String
   let email: String
   let address: Address?
   let role: Role
}

// 2
struct Address {
    
   let street: String
}

// 3
enum Role {
    
   case admin
   case member
   case guest

   var permissions: [Permission] {
    
       switch self {
    
       case .admin:
           return [.create, .read, .update, .delete]
       case .member:
           return [.create, .read]
       case .guest:
           return [.read]
       }
   }
}

// 4
enum Permission {
    
   case create
   case read
   case update
   case delete
}

KeyPath 表达式 \typeName.path

// 1
let stringDebugDescription = \String.debugDescription 
// KeyPath

// 2
let userRole = \User.role 
// KeyPath

// 3
let firstIndexInteger = \[Int][0] 
// WritableKeyPath<[Int], Int>

// 4
let firstInteger = \Array<Int>.first 
// KeyPath<[Int], Int?>

与 Swift 中的大多数内容一样,在可以推断类型的上下文中可以省略类型名称。

在下面的示例中,类型名称可以从显式变量类型推断出来,因此我们可以将类型名称留空。请注意,我们仍然需要\.

let stringDebugDescription : KeyPath<String, String> = \.debugDescription
keyPath 访问值
var user = User(
   name: "Sarunw",
   email: "sarunw@example.com",
   address: nil,
   role: .admin)

let userRoleKeyPath = \User.role
//  WritableKeyPath<User, Role>

// 1
let role = user[keyPath: userRoleKeyPath]
print(role) // admin

// 2
user[keyPath: userRoleKeyPath] = .guest

print(user.role) // guest

场景描述

假设我们正在开发一个电影信息的应用,我们有一个Movie结构体表示电影的信息,其中包括标题、导演、评分等属性。我们希望在用户界面中显示电影信息,同时支持根据电影的不同属性进行排序。

使用Keypath的好处

使用Keypath,我们可以在运行时指定需要排序的属性,同时保持类型安全,避免了硬编码字符串。这样,我们可以在代码中更方便地使用各种属性进行排序,而无需手动编写每个属性的比较函数。

实际应用

首先,我们定义一个Movie结构体:

struct Movie {
    
   let title: String
   let director: String
   let rating: Double
}

然后,我们创建一个包含电影信息的数组:

let movies = [
   Movie(title: "Inception", director: "Christopher Nolan", rating: 8.8),
   Movie(title: "The Dark Knight", director: "Christopher Nolan", rating: 9.0),
   Movie(title: "Interstellar", director: "Christopher Nolan", rating: 8.6),
   // ... 其他电影
]

现在,假设我们希望按照电影的评分进行排序。我们可以使用Keypath来实现这个需求:

let sortedByRating = movies.sorted(by: \.rating)

上述代码中,\.rating表示一个Keypath,它引用了Movie结构体的rating属性。我们将这个Keypath传递给sorted(by:)方法,这样就可以按照评分对电影数组进行排序了。

我们还可以进一步扩展,按照不同的属性进行排序:

let sortedByTitle = movies.sorted(by: \.title)
let sortedByDirector = movies.sorted(by: \.director)

这样,我们可以灵活地在不同场景下按照不同属性对电影数组进行排序,而无需编写多个比较函数或者使用字符串进行硬编码。

我们还有一个特殊的路径,可以引用整个实例而不是属性。我们可以使用以下语法创建一个\.self

var foo = "Foo"
// 1
let stringIdentity = \String.self
//  WritableKeyPath<String, String>

foo[keyPath: stringIdentity] = "Bar"
print(foo) // Bar

struct User {
    
 let name: String
}
var user = User(name: "John")
// 2
let userIdentity = \User.self
// WritableKeyPath<User, User>

user[keyPath: userIdentity] = User(name: "Doe")
print(user) // User(name: "Doe")

总结

Keypath是Swift中一个强大的特性,可以让我们更方便地引用和操作对象的属性,同时保持类型安全。在实际开发中,Keypath可以用于各种场景,包括排序、KVO(键值观察)等。通过上述案例,我们看到了如何在一个电影信息应用中使用Keypath来灵活地进行属性排序。

相关文章
|
4月前
|
存储 算法 Swift
swift中的set特性
swift中的set特性
18 1
|
4月前
|
Swift
swift中Set 的基本操作
swift中Set 的基本操作
18 1
|
7月前
|
Swift
22 Swift中的字典
Swift中的字典
37 0
|
7月前
|
Swift iOS开发
9 如何在Swift中使用Optional
如何在Swift中使用Optional
37 2
|
4月前
|
存储 算法 安全
【Swift专题】聊聊Swift中的属性
属性是面向对象语言中非常基础的语法特性,我们讲属性,实际上就是讲与类本身或类实例关联的数据。在面向对象的语言中,类作为重要的数据结构会封装数据与函数,类中的函数我们通常称其为方法,而数据则就是属性。
43 1
|
4月前
|
Swift
在Swift中,创建一个Set集合
在Swift中,创建一个Set集合
20 1
|
4月前
|
存储 Swift
在Swift编程语言中,Set
在Swift编程语言中,Set
25 2
|
Swift
Swift - 字典
Swift - 字典
65 0
|
安全 编译器 API
Swift 中的幻象类型
模糊的数据可以说是一般应用程序中最常见的错误和问题的来源之一。虽然 Swift 通过其强大的类型系统和完善的编译器帮助我们避免了许多含糊不清的来源——但只要我们无法在编译时保证某个数据总是符合我们的要求,就总是有风险,我们最终会处于含糊不清或不可预测的状态。
97 0
Swift 中的幻象类型
|
测试技术 Swift 索引
Swift:Array+Extension
Swift:Array+Extension
170 0

相关课程

更多