【问题标题】:Can I compile swift code such that public is internal, and vice versa?我可以编译 swift 代码,使 public 是内部的,反之亦然?
【发布时间】:2021-04-05 17:43:45
【问题描述】:

我正在创建一个小型可嵌入的 swift 库。我希望这个库既可以作为常规 swiftpm 包使用,也可以作为单个文件作为内部实现细节复制/粘贴到另一个库中。
我想这样做是为了解决“传递依赖”问题——例如给定:

  • MyApp 引用 BigLib:v2
  • BigLib:v2 引用 SmallLib:v1

现在有一个来自MyApp -> BigLib:v2 -> SmallLib:v1 的传递依赖

但是如果MyApp 也想引用SmallLib:v2 怎么办?我们最终会遇到SmallLib 的 v1 和 v2 都被引用的场景,据我了解,这在 Swift/Xcode/SwiftPM 世界中是无法做到的。

我的想法是,如果我的SmallLib 可以复制/粘贴到BigLib 项目中并制作为内部代码,那么从外部代码(例如MyApp)的角度来看,它将不复存在并且不会有冲突.

这使我进入了在 C++ 中我会(ab)使用预处理器并执行以下操作的部分:

#if !defined(SMALLLIB_EMBEDDED)
#define SMALLLIB_PUBLIC public
#else
#define SMALLLIB_PUBLIC internal
#endif

SMALLLIB_PUBLIC protocol SmallProtocol {
   ...
}

在这样的方案下,BigLib 可以定义 SMALLLIB_EMBEDDED 编译器标志以使 SmallLib 内容不公开,一切都会好起来的。

这样的事情在swift中可以实现吗?

还有其他方法可以解决传递依赖问题吗?

【问题讨论】:

  • 在此期间我要做的是将 SmallLib 的源代码复制/粘贴到 BigLib 中的步骤是手动搜索 / 用 /*public*/ 替换 public 以将其注释掉.有一些不依赖手动搜索/替换的东西会很好!

标签: ios swift preprocessor swift-package-manager


【解决方案1】:

要获得这种行为,最好的办法就是使用 5.3+ 编译器中隐藏的 @_spi 功能。将其添加到语言的 PR 是 here

您需要做的是用@_spi(public) 或您想要的任何标识符标记每种类型和功能,然后复制它的人将能够访问它们,并且只有那些使用@_spi(public) import SmallLib 导入您的模块的人才能访问它们,而您应该能够访问所有这些成员。

当然,这是一个尚未经过进化的隐藏功能,这意味着它在正式发布之前可能至少会发生一些变化。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-14
    • 2012-06-13
    • 2020-07-08
    • 2013-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多