How to Use Third Party Lib in Embedded Dynamic Framework for iOS with Swift

Build Swift dynamic framework with third party static framework as a single framework

A static framework is by definition a fat static library combined with any additional required resources. As such you can embed your third party static library inside your own and also include images, storyboards, plist etc.

You can't do that in a static library (i.e. *.a), but in a static framework you can do.
See for example https://www.raywenderlich.com/65964/create-a-framework-for-ios for details on how to do that (at the end of the article it creates the static *.framework out of the static *.a and some resources)

A dynamic framework can never embed a third party static library. The main application that imports the dynamic framework will always have to also explicitly link against the static library, which it seems that is not what you want.

How can I use a 3rd party Framework inside my CocoaTouchFramework and my consuming App?

Ok I've found a way to do it. I was able to solve the problem by dragging the AlamoFire.Framework into my framework (in this case, AlamoFramework) in Xcode. The important part that makes this work is to check the 'Copy items if needed' checkbox.

Sample Image

After checking this, the compiler can resolve the Alamofire module and there are also no linker issues. However this approach seems to contradict the recommendation of Rob Napier in his answer to this question that states:

The only appropriate time to link dependencies is at the application layer.

I haven't done full-time iOS development for very long so if anyone has any input they can give to clear up this issue, that would be great. But my problem has been fixed for now so I can continue with development.

How to properly embed 3rd party .dylib files in iOS app project for App Store release?

You must add and embed all your shared libraries (.dylib files) directly to the toplevel application the same way as frameworks. You mustn't put dylibs inside a framework because Apple strongly recommends not to use such frameworks (known as Umbrella frameworks) and doesn't accept applications with such frameworks to AppStore (it is a reason for error ITMS-90171).

As Apple documentation says:

An umbrella framework is a framework bundle that contains other
frameworks. While it is possible to create umbrella frameworks for
macOS apps, doing so is unnecessary for most developers and is not
recommended. Umbrella frameworks are not supported on iOS, watchOS, or
tvOS.

How to add a Swift package manager as a dynamic library in xcode 13?

Packages can produce dynamic libraries but they have to explicitly tell Xcode that they want the library to be made into a dynamic library. Realm does not do this. Instead, the folks at Realm go with the default behavior which lets Xcode decide which whether it will construct a static or dynamic library. As far as I know, Xcode always chooses to build a static library.

To get around this you can create your own package that includes the Realm package as a dependency and explicitly make your library dynamic. You can find plenty of tutorials that show you how to make a package so I won't get into that here.

If you create a package and load the following content into your Package.swift file, then import the package into your project, you will have solved your problem. I named my package "RealmUmbrella" but you can call yours whatever you like.

import PackageDescription

let package = Package(
name: "RealmUmbrella",
platforms: [.iOS(.v14)],
products: [
.library(
name: "RealmUmbrella",
type: .dynamic,
targets: ["RealmUmbrella"]
),
],
dependencies: [
.package(name: "Realm", url: "https://github.com/realm/realm-cocoa", "10.0.0"..<"11.0.0")
],
targets: [
.target(
name: "RealmUmbrella",
dependencies: [.product(name: "RealmSwift", package: "Realm")]
),
]
)

Notice how I specify .dynamic here:

        .library(
name: "RealmUmbrella",
type: .dynamic,
targets: ["RealmUmbrella"]
),

Once I added my umbrella package into my project, I clicked on the project file in the project navigator, selected my target, then navigated to "General" tab and scrolled down to "Frameworks, Libraries, and Embedded Content". Then I specified, "Embed and Sign" in the "Embed" column for my package.

Sample Image

And that's it.

Library? Static? Dynamic? Or Framework? Project inside another project

First, some general definitions (specific to iOS):

Static library - a unit of code linked at compile time, which does not change.

However, iOS static libraries are not allowed to contain images/assets (only code). You can get around this challenge by using a media bundle though.

A better, more formal definition can be found on Wikipedia here.

Dynamic library - a unit of code and/or assets linked at runtime that may change.

However, only Apple is allowed to create dynamic libraries for iOS . You're not allowed to create these, as this will get your app rejected. (See this other SO post for confirmation and reasoning on such).

Software Framework - a compiled set of code that accomplishes a task... hence, you can actually have a static framework or a dynamic framework, which are typically just the compiled versions of the above.

See the Wiki on Software Framework for more details.

Hence on iOS, your only option is basically to use a static library or static framework (the main difference being that a static framework is distributed as a compiled .a file most often, whereas a static library may simply be included as a subproject - you can see all of the code - which is compiled first and its resulting .a file used as a dependency by the project).

Now that we're clear(er) on these terms, setting up a static library and supporting media bundle for iOS isn't too difficult, and there are many tutorials on how to do such. I personally would recommend this one:

https://github.com/jverkoey/iOS-Framework

This is a pretty straight-forward guide and doesn't have the disadvantage of dealing with "fake static libraries"... check it out for more info...

Once you've created your static library, it's as easy as including it as a submodule within Git for use across different projects.

Good Luck.

EDIT

Regarding a subproject within a project, as far as I know, to get this to work/compile correctly, you essentially have to set up a compile chain where the subproject is compiled first, which creates a static framework .a file that is used as a dependency by the project.

Here's another useful tutorial which talks about this:

http://www.cocoanetics.com/2011/12/sub-projects-in-xcode/

EDIT 2

As of iOS 8, Apple now permits developers to create dynamic frameworks! (Note: your app must have a minimum target of iOS 8 to include a dynamic framework... back porting isn't allowed.)

This has been added as a new project template. In Xcode 6.1, this can be found at:

New Project -> iOS -> Framework & Library -> Cocoa Touch Framework

How to I import 3rd party frameworks into Xcode Playground?

Edited: As of Beta5 this is now supported when the playground is part of the workspace that builds the framework as a target. There are more details on the Apple dev forums site, but hopefully @Rick Ballard will add them to his answer here and that should becoke the definitive answer for this question.

Don't do the below anymore!


For the short term, while there's no supported solution, if you're producing a Module/Framework you can copy it into the SDKs System/Library/Frameworks directory and then just import <#Module#> the same way as you import system Frameworks.

For an OS X Playground: /Applications/Xcode6-Beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/System/Library/Frameworks

And for iOS: /Applications/Xcode6-Beta.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator8.0.sdk/System/
Library/Frameworks/

But before you do that... go file a radar as @Rick says in his answer.



Related Topics



Leave a reply



Submit