I'm relatively new to Swift and building software for Apple platforms. So far I'm enjoying it, but one of the things that struck me from the beginning was leaky dependencies/imports.
This is something that has been discussed extensively in the community, and some solid proposals have been tabled, kick-started by @jrose on the @_implementationOnly work.
A snippet from the 'exported-and-fixing-import-visibility' post to summarise the problem
Today, if your Swift library "Foo" uses a library "Bar", the headers (or swiftmodule files) of "Bar" must be available to all clients of "Foo". This is clearly undesirable, especially when "Bar" is just an implementation detail. (It may even be linked statically.)
More literature on the topic here:
- @_exported and fixing import visibility (first post)
- Update on implementation-only imports (update on the prototype solution)
- [Pre-Pitch] Import access control: a modest proposal (latest pitch and state of things now)
Another forum post also highlights a setup very similar to the one below and illustrates the problem,
As the above post states (and my early understanding assumes) If we have a setup like so:
Static library named InternalLibrary
. InternalLibrary
is statically linked into a framework called FrameworkA
.
An iOS App Target embeds and links FrameworkA
.
At this point, most of the literature I've read about this states that the App Target would now also need to link to InternalLibrary
. This is exactly what @ylorn experiences in their post.. This makes sense as to why proposals like @_implementationOnly (and perhaps an internal import) exist. For example, If InternalLibrary
was brought in with @_implementationOnly
inside FrameworkA
, then it would make sense for the App Target to not require an explicit link to InternalLibrary.
I believe I have a good enough grasp of this. However, when the above setup is tried with Xcode 14.1 with the iOS 16.1 App Target, I can omit the need to link to InternalLibrary
in the App Target. This works if InternalLibrary
is either a Cocoa Touch Static Library or a Swift Package which produces a static library. This seems to go against my understanding and a lot of the discussion around this issue.
To expand a little more, InternalLibrary is still found on the public interface of FrameworkA
. And the App Target can still import and use InternalLibrary
, so a solution like @_implementationOnly would be better, but my question is, how does the above solution work? And is it a bad idea?
Note: I've build and run on simulator and device.