🏷 标签

Twitter Swift Swift Package Manager Compatible

欢迎使用 Tagging,这是一个小型库,可以轻松地在 Swift 中创建类型安全的标签。分类对于我们的模型通常非常有用,因此利用编译器确保它们以正确的方式使用,对于使应用程序或系统的模型层更加健壮大有帮助。

这个库强烈受到 JohnSundell/🆔entitymbleigh/acts-as-taggable-on 的启发。有关理论信息,请查看 Swift by Sundell 上的 "Swift 中的类型安全标识符"

使类型可标记

要使用 Tagging,您只需使模型遵循 Taggable 协议,并为其提供一个 tags 属性,如下所示:

struct Article: Taggable {
    let tags: [Tag<Article>]
    let title: String
}

这样,上面的 Article 标签现在就是类型安全的了! 感谢 Swift 的类型推断能力,也可以通过使用 Tags 作为其类型来实现 Taggable 类型的 tags

struct Article: Taggable {
    let tags: Tags
    let title: String
}

Tags 类型别名会自动为所有 Taggable 类型添加,这使得可以将 [Tag<Article>] 称为 Article.Tags

自定义原始类型

Tag 值默认由字符串支持,但是可以通过给 Taggable 类型一个 RawTag 轻松地进行自定义,但必须至少是 Hashable

struct Article: Taggable {
    typealias RawTag = UUID

    let tags: Tags
    let title: String
}

上面的 Article 标签现在由 UUID 而不是 String 支持。

内置便利功能

即使 Tagging 专注于类型安全,它仍然提供了几个便利的功能来帮助减少冗长。例如,如果 Tag 由一个可以通过 String 字面量表示的原始值类型支持,那么标签也可以:

let article = Article(tags: ["foo", "bar"], title: "Example")

对于由可以通过 Int 字面量表示的原始值类型支持的标签,情况也是如此:

let article = Article(tags: [7, 9], title: "Example")

Tag 的原始值类型符合这些协议之一时,Tag 也变为 CodableHashableEquatable

类型安全

那么 Tagging 究竟是如何使标签更具类型安全的呢? 首先,当使用 Tagging 时,不再可能意外地将一种类型的标签传递给接受另一种类型标签的 API。 例如,以下代码在使用 Tagging 时将无法编译:

articleManager.articles(withTags: user.tags)

上面的编译器会给我们一个错误,因为我们试图将 [Tag<User>] 值传递给一个接受 [Tag<Article>] 的方法 - 与使用纯值(例如 StringInt)作为标签类型相比,这为我们提供了更强的类型安全。

Tagging 还使得不可能意外地声明错误类型的 tags 属性。 因此,以下内容也无法编译:

struct User: Tagging {
    let tags: [Tag<Article>]
}

上面的代码将无法编译的原因是 Taggable 要求符合它的类型声明与 conformer 类型相同的标签,再次提供了额外的类型安全级别。

查找最多或最少使用的标签

您可以使用以下方法查找最多或最少使用的标签:

taggableCollection.mostUsedTags()
taggableCollection.leastUsedTags()

您还可以通过向该方法传递一个限制来过滤结果,但是默认限制为 20。

taggableCollection.mostUsedTags(10)
taggableCollection.leastUsedTags(10)

或者直接获取原始值。

taggableCollection.mostUsedRawTags()
taggableCollection.leastUsedRawTags()

查找已标记的对象

注意:默认情况下,查找使用任何指定标签标记的对象。
taggableCollection.tagged(with: "foo")
taggableCollection.tagged(with: ["foo"])
taggableCollection.tagged(with: ["foo", "bar"])
taggableCollection.tagged(with: taggable.tags)

查找与所有给定标签匹配的已标记对象

注意:这仅匹配具有确切指定标签集的已标记对象。 如果已标记对象具有其他标签,则不会返回它们。
taggableCollection.tagged(with: ["foo", "bar"], match: .all)
taggableCollection.tagged(with: taggable.tags, match: .all)

查找没有用给定标签标记的对象

taggableCollection.tagged(with: ["foo", "bar"], match: .none)
taggableCollection.tagged(with: taggable.tags, match: .none)

安装

由于 Tagging 是在一个 单个文件 中实现的!,最简单的方法就是直接将其拖放到您的 Xcode 项目中。

但是,如果您希望使用依赖项管理器,则可以使用 Swift Package Manager,方法是在您的 Package.swift 文件中将 Tagging 声明为依赖项:

.package(url: "https://github.com/alexruperez/Tagging", from: "0.1.0")

有关更多信息,请参见 Swift Package Manager 文档

贡献 & 支持

Tagging 是完全公开开发的,非常欢迎您的贡献。

在开始在任何项目中使用 Tagging 之前,强烈建议您花几分钟时间熟悉其文档和内部实现(所有内容都在一个文件中!),这样您就可以准备好解决可能遇到的任何问题或极端情况。

要了解有关用于实现 Tagging 的原理的更多信息,请查看 Swift by Sundell 上的 "Swift 中的类型安全标识符"

此项目不提供基于 GitHub Issues 的支持,而是鼓励用户积极参与其持续开发 - 通过修复他们遇到的任何错误或改进发现不足的文档。

如果您希望进行更改,请打开一个 Pull Request - 即使它仅包含您计划的更改草案或重现问题的测试 - 然后我们可以从那里进一步讨论它。

希望您喜欢使用 Tagging! 😀