欢迎使用 Identity,这是一个小型的 Swift 库,可以轻松创建类型安全的标识符。 标识符通常是代码库中引用模型和其他值的核心,因此利用编译器来确保它们以正确的方式使用,可以大大提高应用程序或系统模型层的稳健性。
有关更多信息,请查看 Swift by Sundell 上的"Swift 中的类型安全标识符"。
要使用 Identity,您只需使模型符合 Identifiable
协议,并为其提供一个 id
属性,如下所示:
struct User: Identifiable {
let id: Identifier<User>
let name: String
}
就这样,上面的 User
标识符现在是类型安全的了! 感谢 Swift 的类型推断功能,也可以通过简单地使用 ID
作为类型来实现 Identifiable
类型的 id
:
struct User: Identifiable {
let id: ID
let name: String
}
ID
类型别名会自动为所有 Identifiable
类型添加,这也使得可以将 Identifier<User>
称为 User.ID
。
Identifier
值默认由字符串支持,但这可以通过为 Identifiable
类型提供 RawIdentifier
轻松进行自定义:
struct Article: Identifiable {
typealias RawIdentifier = UUID
let id: ID
let title: String
}
上面的 Article
标识符现在由 UUID
而不是 String
支持。
即使 Identity 专注于类型安全,它仍然提供了一些便捷功能来帮助减少冗长。 例如,如果 Identifier
由一个可以通过 String
字面量表示的原始值类型支持,那么该标识符也可以:
let user = User(id: "johnsundell", name: "John Sundell")
对于由可以用 Int
字面量表示的原始值类型支持的标识符,同样如此:
let tag = Tag(id: 7, name: "swift")
当其原始值类型符合这些协议之一时,Identifier
也会变成 Codable
、Hashable
和 Equatable
。
那么 Identity 到底是如何使标识符更加类型安全的呢? 首先,在使用 Identity 时,不再可能意外地将一种类型的标识符传递给接受另一种类型标识符的 API。 例如,当使用 Identity 时,此代码将无法编译:
articleManager.article(withID: user.id)
由于我们试图将 Identifier<User>
值传递给接受 Identifier<Article>
的方法,编译器会给出错误提示——与使用普通值(如 String
或 Int
)作为标识符相比,这提供了更强大的类型安全性。
Identity 还使得不可能意外地声明错误类型的 id
属性。 因此,以下代码也无法编译:
struct User: Identifiable {
let id: Identifier<Article>
}
上面的代码无法编译的原因是 Identifiable
要求符合它的类型声明与 conformer 类型绑定的标识符,再次提供额外的类型安全级别。
由于 Identity 是在一个文件中实现的,因此使用它的最简单方法是直接将其拖放到您的 Xcode 项目中。
但是,如果您希望使用依赖管理器,则可以通过在 Package.swift
文件中将 Identity 声明为依赖项来使用 Swift Package Manager:
.package(url: "https://github.com/JohnSundell/Identity", from: "0.1.0")
有关更多信息,请参阅 Swift Package Manager 文档。
Identity 完全以开放的方式开发,我们非常欢迎您的贡献。
在任何项目中使用 Identity 之前,强烈建议您花几分钟时间熟悉其文档和内部实现(所有内容都在一个文件中!),以便您可以准备好解决可能遇到的任何问题或边缘情况。
要了解有关用于实现 Identity 的原则的更多信息,请查看 Swift by Sundell 上的"Swift 中的类型安全标识符"。
本项目不提供基于 GitHub Issues 的支持,而是鼓励用户积极参与其持续开发 - 通过修复他们遇到的任何错误,或者改进发现不足的文档。
如果您希望进行更改,请打开一个 Pull Request - 即使它只包含您计划进行的更改的草稿或重现问题的测试 - 我们可以在那里进一步讨论它。
希望您喜欢使用 Identity! 😀