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

相关文章
|
应用服务中间件 API nginx
Nginx到底是怎么转发的
Nginx到底是怎么转发的
175 1
|
前端开发 应用服务中间件 Linux
Gin-Vue-Admin 线上部署
Gin-Vue-Admin 线上部署
950 0
Gin-Vue-Admin 线上部署
|
网络协议 Linux 开发工具
Linux|麒麟操作系统实现多路RTMP|RTSP播放
无论是Windows平台还是Linux,多路播放诉求非常普遍,比如针对智慧工地、展馆、教育等宏观场景下的摄像头展示,关于RTSP或RTMP直播播放器开发需要注意的点,可参考之前博客,总的来说有以下一些点:
365 0
这一篇让你彻底搞懂贝塞尔曲线
贝塞尔曲线不懂画?不知道怎么回事?看这一篇就够了!用图形,点曲线运动图和公式推导,让你彻底搞懂贝塞尔曲线的运行原理!
3388 0
这一篇让你彻底搞懂贝塞尔曲线
|
9月前
|
缓存 移动开发 小程序
uni-vue3-wetrip自创跨三端(H5+小程序+App)酒店预订app系统模板
vue3-uni-wetrip原创基于vite5+vue3+uniapp+pinia2+uni-ui等技术开发的仿去哪儿/携程预约酒店客房app系统。实现首页酒店展示、预订搜索、列表/详情、订单、聊天消息、我的等模块。支持编译H5+小程序+App端。
312 8
|
存储 编译器
【.NET Core】特性(Attribute)详解
【.NET Core】特性(Attribute)详解
550 2
|
分布式计算 Hadoop Java
Hadoop MapReduce 调优参数
对于 Hadoop v3.1.3,针对三台4核4G服务器的MapReduce调优参数包括:`mapreduce.reduce.shuffle.parallelcopies`设为10以加速Shuffle,`mapreduce.reduce.shuffle.input.buffer.percent`和`mapreduce.reduce.shuffle.merge.percent`分别设为0.8以减少磁盘IO。
189 1
|
Unix 编译器 iOS开发
苹果AppleMacOs系统Sonoma本地部署无内容审查(NSFW)大语言量化模型Causallm
最近Mac系统在运行大语言模型(LLMs)方面的性能已经得到了显著提升,尤其是随着苹果M系列芯片的不断迭代,本次我们在最新的MacOs系统Sonoma中本地部署无内容审查大语言量化模型Causallm。 这里推荐使用koboldcpp项目,它是由c++编写的kobold项目,而MacOS又是典型的Unix操作系统,自带clang编译器,也就是说MacOS操作系统是可以直接编译C语言的。
苹果AppleMacOs系统Sonoma本地部署无内容审查(NSFW)大语言量化模型Causallm
|
JavaScript Java 测试技术
基于springboot+vue.js的系统附带文章和源代码设计说明文档ppt
基于springboot+vue.js的系统附带文章和源代码设计说明文档ppt
268 1
|
编译器 C语言
动态内存分配—malloc calloc realloc free 和常见动态内存错误
我们熟知的内存开辟方式有两种:第一种便是通过等关键字为变量开辟空间;第二种便是通过开辟一段连续的空间。这样开辟的空间很局限:1. 空间开辟大小是固定的。2. 数组在声明的时候,必须指定数组的长度,它所需要的内存在编译时分配。动态内存分配所开辟的空间在堆区,并且是可以扩容的。
272 1