好的...这很难解释(并且很难给它起一个标题),但是我会尽力而为。
我们在使用Carthage导入东西时首先发现了这一点,但是在Xcode中设置了一个示例项目(不使用Carthage),似乎做了相同的事情。
首先,这是我们设置的示例项目的屏幕截图...
具有目标 Test20000 ,并且具有依赖项 A 。
A 框架然后依赖于 B 。
Test20000 应用没有不添加 B 作为直接依赖项。
B 中有一个类似...的结构
import Foundation
public struct BType {
public let value = "Hello, B!"
}
在 A 中,有一个类似...的文件
import Foundation
import B
public struct AType {
public let value = "Hello, A!"
public func doAThing() {
print(BType().value)
}
}
现在,在 Test20000 应用中,我们可以执行以下操作...
import Foundation
import A
struct TestType {
func doSomething() {
let aType = AType()
print(aType.value)
aType.doAThing()
}
}
这按预期工作。它会打印...
你好,A! 你好,B!
如果我将功能更改为这样的话...
import Foundation
import A
struct TestType {
func doSomething() {
let bType = BType()
print(bType.value)
}
}
这将不会编译,因为未导入 B ,因此无法访问BType
。
但是!如果您在 B 中声明扩展名,例如...
extension String {
func doAThingInB() {
print(self)
}
}
然后...在不更改导入和依赖项的情况下,我现在可以将应用程序代码更改为...
import Foundation
import A
struct TestType {
func doSomething() {
"Hello, bug!".doAThingInB()
}
}
这将打印出来,就像扩展名是实际应用程序公共的一样。从B到A,再到应用程序,都是“兔子跳”。
我觉得这根本不应该发生。
我们找不到关闭或阻止这种情况发生的方法。
这是一个错误吗?
我们需要做些什么来阻止这种情况吗?
谢谢
答案 0 :(得分:1)
我试图利用private module maps来隐藏内部框架,使其对A
的用户不可见,但运气不佳。可能与[SR-2896] Private modulemaps do no work properly相关。
我想这是目前的预期行为。 swift.org论坛上有多种建议可以实现您想要的东西,例如Namespaces x submodules或更相关的@_exported and fixing import visibility。
最后一个的相关部分:
当今的Swift的设计更像Java,C#或Python,因为如果您在Foo的实现中导入Bar,则不会影响导入Foo的客户。或者,好吧,它使导入Foo的客户无法看到Bar的顶级名称。
您仍然需要使用Bar,因为编译器不会跟踪您是否在Foo的公共界面中使用了其中一种类型。 (这是上一节。)
- 导入Foo的客户端仍然可以看到
导入Foo的客户端仍然可以看到Bar中的扩展名,因为编译器无法区分扩展名来自今天。
Bar中的运算符声明,因为编译器以不同于查找顶层所有其他内容的方式来找到运算符。
最后一条消息之一:
本次讨论的总体结果是,对于Swift vNext来说,做任何聪明的事都不值得:只需添加“仅实现导入”和“导出导入”,其余就暂时解决。
答案 1 :(得分:1)
好的...所以Swift团队的回应...
https://bugs.swift.org/browse/SR-9913
这是他们一段时间以来所知道的。而且他们不希望很快修复它。
所以,是的,这是一个错误。 但是,不,没有任何方法可以解决它。
我猜想修复它所引起的问题要比解决更改方面的问题多。