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来灵活地进行属性排序。

相关文章
|
7月前
|
存储 算法 Swift
swift中的set特性
swift中的set特性
50 1
|
7月前
|
Swift
swift中Set 的基本操作
swift中Set 的基本操作
66 1
|
Swift iOS开发
9 如何在Swift中使用Optional
如何在Swift中使用Optional
79 2
|
Swift
22 Swift中的字典
Swift中的字典
67 0
|
Swift 索引
18 在Swift中创建一个数组
在Swift中创建一个数组
346 0
|
1月前
|
存储 Swift iOS开发
Swift 字典
10月更文挑战第27天
24 2
|
7月前
|
存储 算法 安全
【Swift专题】聊聊Swift中的属性
属性是面向对象语言中非常基础的语法特性,我们讲属性,实际上就是讲与类本身或类实例关联的数据。在面向对象的语言中,类作为重要的数据结构会封装数据与函数,类中的函数我们通常称其为方法,而数据则就是属性。
103 1
|
7月前
|
Swift
在Swift中,创建一个Set集合
在Swift中,创建一个Set集合
76 1
|
7月前
|
存储 Swift
在Swift编程语言中,Set
在Swift编程语言中,Set
77 2
|
Swift
Swift - 字典
Swift - 字典
90 0

相关课程

更多