Swift 来自框架的类型扩展';应用程序中可用的依赖项

Swift 来自框架的类型扩展';应用程序中可用的依赖项,swift,frameworks,Swift,Frameworks,好的。。。这很难解释(也很难给它起个名字),但我会尽力的 我们第一次发现这一点是在使用Carthage导入东西时,但在Xcode中设置一个示例项目(不使用Carthage)似乎也做了同样的事情 首先,这里是我们设置的示例项目的屏幕截图 测试对象有一个targetTest20000,它有一个dependencya A框架随后依赖于B 重要的 Test20000应用程序不会将B添加为直接依赖项 框架 在B中有一个类似于 import Foundation public struct BType

好的。。。这很难解释(也很难给它起个名字),但我会尽力的

我们第一次发现这一点是在使用Carthage导入东西时,但在Xcode中设置一个示例项目(不使用Carthage)似乎也做了同样的事情

首先,这里是我们设置的示例项目的屏幕截图

测试对象有一个targetTest20000,它有一个dependencya

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()
    }
}
extension String {
    func doAThingInB() {
        print(self)
    }
}
这正如预期的那样有效。它打印

你好,A! 你好,B

如果我把函数改成这样

import Foundation
import A

struct TestType {
    func doSomething() {
        let bType = BType()

        print(bType.value)
    }
}
由于未导入B,因此无法访问
B类型,因此不会编译该文件

接球! 然而!如果您在B中声明扩展名,例如

import Foundation
import A

struct TestType {
    func doSomething() {
        let aType = AType()

        print(aType.value)
        aType.doAThing()
    }
}
extension String {
    func doAThingInB() {
        print(self)
    }
}
那么现在。。。在不更改导入和依赖项的情况下,我现在可以将我的应用程序代码更改为

import Foundation
import A

struct TestType {
    func doSomething() {
        "Hello, bug!".doAThingInB()
    }
}
这将打印出来,就好像扩展对实际应用程序是公开的一样。它有点像“兔子跳”,从B跳到A,然后进入应用程序

我觉得这根本不应该发生

我们无法找到一种方法来关闭或阻止这种情况发生

这是虫子吗

我们需要做些什么来阻止这一切吗


谢谢

我曾试图利用来隐藏内部框架,使其不被
A
的用户看到,但没有成功。可能与……有关

我想这是目前人们所期待的行为。在swift.org论坛上有多个建议来实现您想要的东西,例如,或更相关的建议

上一篇文章的相关部分:

今天的Swift设计得更像Java、C#或Python,因为如果在Foo的实现中导入Bar,它不会影响导入Foo的客户机。或者,它不会让导入Foo的客户看到Bar的顶级名称

  • 您仍然需要使用Bar,因为编译器不会跟踪您是否在Foo的公共接口中使用了它的类型之一。(这是上一节。)

  • Bar中的扩展仍然对导入Foo的客户机可见,因为编译器不区分今天的扩展来自何处

  • Bar中的运算符声明仍然对导入Foo的客户机可见,因为编译器查找运算符的方式不同于它在顶层查找所有其他运算符的方式

  • 从最后一条消息中:

    这一讨论的总体结果是,可能不值得为Swift vNext做任何聪明的事情:只需添加“仅实现导入”和“导出导入”,暂时不处理其余部分


    我很高兴知道是否有解决办法,但没有。

    好的。。。所以Swift团队的回应

    这是他们早就知道的事情。而且他们也不打算在短期内解决这个问题

    所以,是的,这是一个错误。 但是,不,没有任何办法解决它

    我猜修复它会导致比修复破坏性更改更多的问题