当传递字符串或整数作为 ID 时,编译器不会提示你是否将 person ID 传递到了 blog post ID 的位置。现在有了 UniquelyTypedID
,编译器将阻止你传递不同模型的 ID。
并且凭借 ExpressibleByStringLiteral
和 ExpressibleByIntegerLiteral
的强大功能,只需要修改极少量的代码。
我已经在自己的项目中使用了这种方法来保证记录 ID 的类型安全,通常是通过手动复制粘贴实现的。现在有了 Swift 5.9 中的 Swift 宏,这将变得容易得多。
在 Package.swift 中,将此包添加到你的依赖项中。
.package(url: "https://github.com/FullQueueDeveloper/UniquelyTypedID.git", from: "1.0.0"),
并将 "UniquelyTypedID"
添加到你的 target 依赖项列表中。
当 Xcode 提示时,信任该宏。
如果你有一个整数 ID
struct BlogPost {
let id: Int
let text: String
}
那么你可以使用这个宏来代替。
struct BlogPost {
@UniquelyTypedId(Int.self) let id: ID
let text: String
}
其中 ID
是你希望的 ID 类型名称。我倾向于简单地使用 ID
,这样我可以轻松地通过 BlogPost.ID
引用该类型。
目前,支持 Int
、String
和 UUID
。如果没有指定类型,该宏默认使用 UUID
。
所有生成的 ID 都是 Hashable
的。
所有生成的 ID 都是 Codable
的,并且它们编码为单值容器,以便在从普通整数或字符串 ID 升级时获得最大的兼容性。
由 UniquelyTypedId
生成的字符串 ID 类型可以通过字符串字面量表达。这使得硬编码数据输入更加容易。
struct Vegetable {
@UniquelyTypedId(String.self) let scientificName: ScientificName
let name: String
}
let chili = Vegetable(scientificName: "Capsicum annuum", name: "Chili")
如果我们把这个 chili
编码成 JSON,我们会看到
{
"name" : "Chili",
"scientificName" : "Capsicum annuum"
}
由 UniquelyTypedId
生成的整数 ID 类型可以通过字符串字面量表达。这使得硬编码数据输入更加容易。
例如
struct Aubergine: Codable {
@UniquelyTypedID(Int.self) let id: ID
let name: String
}
let aubergineID: Aubergine.ID = 3
let aubergine = Aubergine(id: 9, name: "Fairy Tale")
在 WWDC '23 上推出,需要 Swift 5.9