Echo

Build Status

Swift 的一个完整的反射包。

文档: Echo Wiki

安装

根据你所针对的 Swift 版本,安装方式和安装的版本可能会有所不同。

示例 1:你是一个 iOS 应用开发者,支持 Swift 5.0 - 5.3。 在这种情况下,你可能需要 swift-5.0 分支,这样就无需担心“我使用的东西是否只在新运行时中可用?”

示例 2:你在 Linux 服务器上使用 Swift,并且想要包含此依赖项。 这很简单,因为无论你运行哪个版本的 Swift,都是你需要包含的分支。 你的 SotS 项目使用 Swift 5.3,因此只需使用 swift-5.3 分支即可。

示例 3:你有一个 macOS 应用程序,仅在 Swift 5.3 上受支持,并且将始终仅支持最新版本的 Swift。 与服务器上的 Swift 示例类似,你只需要最新的 swift-5.3 分支即可。

在了解你需要包含哪个分支后,使用 Swift 包管理器添加依赖项来添加 Echo 就相当简单了。

.package(url: "https://github.com/Azoy/Echo.git", .branch("swift-5.3"))

关于 ABI 稳定性的说明

此库公开了一些元数据数据结构,这些结构在任何平台上都不被认为是 ABI 稳定的,即 Tuple/Existential/Function/Metatype 元数据。 尽管如果你使用的分支与你使用的语言运行时相匹配,这些元数据结构可以工作,但在将来,这些类型可能会中断。 这主要是一些在 ABI 稳定平台上部署应用程序,并且需要代码既适用于旧运行时又适用于新运行时的人所关心的问题。 如果你是这种情况,我强烈建议阅读你正在使用的所有数据结构的文档,以确保你没有使用任何将来可能中断的内容。 如果你是在没有 ABI 稳定性的平台上部署应用程序的开发人员,即 Linux 和 Windows,则这不应该引起你的关注,因为不能保证任何东西都可以在 Swift 版本之间工作,因此由你来更新此依赖项。

用法

一些示例场景

// Perhaps I need the generic argument to whatever type
// is passed in here.
func printGenericArgs<T>(with x: T) {
  guard let metadata = reflect(x) as? TypeMetadata else {
    return
  }

  print(metadata.genericTypes)
}

// [Swift.Int]
printGenericArgs(with: [1, 2, 3])

// [Swift.String, Swift.Int]
printGenericArgs(with: ["Romeo": 128, "Juliet": 129])

或者你可能想访问类型的全部一致性(conformance)

func printAllConformances<T>(for _: T.Type) {
  guard let metadata = reflect(T.self) as? TypeMetadata else {
    print("Not a TypeMetadata type!")
    return
  }

  for conformance in metadata.conformances {
    print("\(metadata.descriptor.name): \(conformance.protocol.name)")
  }
}

// ...
// Int: ExpressibleByIntegerLiteral
// Int: Comparable
// Int: Hashable
// Int: Equatable
// ...
printAllConformances(for: Int.self)