I'd like to determine, definitively, if nesting of "binaries" within other "binaries" is possible with iOS.
I put binaries in quotes because I've read documentation/forum posts stating things like nested frameworks isn't supported in iOS. A framework is a binary isn't it, or contains one. So does a statement such as that apply specifically and only to nested frameworks, or does it also apple to other scenarios - such as a SPM binary integrated into a framework?
Here's the specific scenario I'm seeking clarity on - suppose an SDK providing an API/functionality is built as an .xcframework and that SDK contains dependencies on two other components (Firebase, AlmoFire, RealmSwift, CocoaLumberjack, whatever etc.).
Lets say the SDK has two dependencies X and Y and it integrates them via SPM.
Q1: If there is an app A which integrates the SDK, and A doesn't use X and Y itself, then can X and Y be embedded within the SDK and thus opague to A? Is this possible in iOS?
Q2: If A integrates the SDK as above, but additionally, it itself uses X and Y independently of the SDK, then is this situation possible in iOS?
Presumably in Q1 the SDK needs to embed X and Y into the framework? While presumably in Q2 it should not - because the app will be and hence that would lead to duplicate symbols and potential undefined behaviour (and therefore X and Y's SPM package spec needs to specify dynamic?)
I've been trying to get a clear picture of this for literally weeks and weeks, without reaching a clear conclusion. So some definitive answer would be very much appreciated.
Placing Content in a Bundle is pretty clear about this. Quoting this:
iOS, watchOS, and tvOS support third-party frameworks but don’t support third-party standalone dynamic libraries, which are those outside a framework bundle, typically with the
.dylib
filename extension. The only exception to this rule is the Swift system libraries provided by Xcode.
and this:
iOS and tvOS support frameworks and Swift system libraries at the topmost app level; a nested bundle, like an app extension, can’t include a framework.
So the runtime story is fairly simple:
-
An iOS app can embed app extensions, system extensions, frameworks, and Swift system libraries.
-
But only at the top level.
To talk about this in more depth, we need better terminology. The terminology I use is outlined in An Apple Library Primer.
Lets say the SDK has two dependencies X and Y and it integrates them via SPM.
This is asking about the build-time story, and that’s substantially more complicated:
-
There are dynamic and static libraries, but only dynamic libraries affect the runtime story.
-
Swift Package Manager can produce both either, depending on how you configure it.
-
Xcode 15 and later support static frameworks.
-
Xcode 15 and later support mergeable libraries.
-
XCFrameworks support static libraries, dynamic libraries, and frameworks, where the last two may or may not be mergeable.
Finally, there’s an deeper issue that you haven’t touched on here, namely the namespaces associated with Objective-C and Swift. I recently covered your dependency issue in another thread and I’ve just updated that thread to properly explain the namespace issue.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"