OK... esto es difícil de explicar (y de encontrar un título) pero haré lo mejor que pueda.
Descubrimos esto por primera vez cuando usamos Carthage para importar cosas, pero al configurar un proyecto de muestra en Xcode (sin usar Carthage) parece haber hecho lo mismo.
Primero, aquí hay una captura de pantalla del proyecto de muestra que configuramos...
Tienen un objetivo Test20000 y tiene una dependencia A .
El marco A entonces tiene una dependencia en B .
La aplicación Test20000 NO agrega B como una dependencia directa.
En B hay una estructura como...
import Foundation public struct BType { public let value = "Hello, B!" }En A hay un archivo como...
import Foundation import B public struct AType { public let value = "Hello, A!" public func doAThing() { print(BType().value) } }Ahora en la aplicación Test20000 hacemos algo como...
import Foundation import A struct TestType { func doSomething() { let aType = AType() print(aType.value) aType.doAThing() } }Esto funciona como se esperaba. Imprime...
¡Hola, A! ¡Hola B!
Si cambio la función a algo como esto...
import Foundation import A struct TestType { func doSomething() { let bType = BType() print(bType.value) } } Entonces esto no se compila porque B no se importa y, por lo tanto, no se puede acceder a BType .
¡Sin embargo! Si declaras una extensión en B algo como...
extension String { func doAThingInB() { print(self) } }Entonces ahora... sin ningún cambio en las importaciones y las dependencias, ahora puedo cambiar el código de mi aplicación a...
import Foundation import A struct TestType { func doSomething() { "Hello, bug!".doAThingInB() } }Y esto se imprimirá como si la extensión fuera pública para la aplicación real. Es una especie de "salto de conejo" de B, sobre A y dentro de la aplicación.
Siento que esto no debería suceder en absoluto.
No podemos encontrar una manera de apagar esto o evitar que esto suceda.
¿Es esto un error?
¿Hay algo que debamos hacer para detener esto?
Gracias
Intenté hacer uso de mapas de módulos privados para ocultar el marco interno para que no sea visible para los usuarios de A , pero no tuve suerte con eso. Podría estar relacionado con [SR-2896] Los mapas de módulos privados no funcionan correctamente .
Supongo que este es el comportamiento esperado en este momento. Hay múltiples propuestas en los foros de swift.org para implementar algo como usted quiere, por ejemplo, Namespaces x submodules o uno más relevante @_exported y arreglar la visibilidad de importación .
Partes relevantes de la última:
El Swift de hoy está diseñado más como Java o C# o Python, en el sentido de que si importa Bar en la implementación de Foo, no afecta a los clientes que importan Foo. O bien, no hace que los nombres de nivel superior de Bar sean visibles para los clientes que importan Foo.
Todavía necesita Bar, porque el compilador no rastrea si ha usado uno de sus tipos en la interfaz pública de Foo. (Esa es la sección anterior).
Las extensiones en Bar todavía se hacen visibles para los clientes que importan Foo, porque el compilador no distingue de dónde provienen las extensiones hoy.
Las declaraciones de operadores en Bar todavía se hacen visibles para los clientes que importan Foo, porque el compilador encuentra operadores de una manera diferente a como encuentra todo lo demás en el nivel superior.
Y de uno de los últimos mensajes:
el resultado general de esta discusión es que probablemente no valga la pena hacer nada inteligente para Swift vNext: solo agregue "importación solo de implementación" y tal vez "importación exportada" y deje el resto solo por ahora.
Me encantaría saber si hay una solución para esto, pero parece que no hay ninguna.
OK... así que la respuesta del equipo de Swift...
https://bugs.swift.org/browse/SR-9913
Esto es algo que saben desde hace tiempo. Y no buscan arreglarlo en el corto plazo.
Entonces, sí, es un error. Pero no, no hay forma de solucionarlo.
Supongo que arreglarlo causaría más problemas de los que arreglaría en términos de cambios importantes.