iOS Frameworks, embed another framework or library? - ios

So in Xcode 6, we finally have the possibility to create and distribute our own libraries as Frameworks (as opposed to Static Libraries before).
The question, is it possible to "embed" another framework or library directly inside the framework rather than ask the end user to link them?
The reason is as follow: Creating and distributing frameworks for other people often requires them to manually add whichever framework we link against.
That's fine when these libraries are a default ones that can be added straight from Xcode, but when we need to link against other public frameworks.
One example would be if the framework uses AWS as a backend, it's a bit overkill to ask developers to also download a specific version of their SDK and link against specific bits that are required. And it becomes more overkill when we need others for performance logging or more.
On OSX, there is the possibility to use Umbrella Frameworks, but it's undocumented on iOS.
Thank you.

Recently done this myself on iOS, unfortunately any framework that has sub-frameworks must also be linked to in the project the parent framework gets used in.
Create the framework as per normal, and include the other frameworks under that framework (it should be an aggregate target).
Then build the parent framework, and link this into the main project. Attempt to compile and it will mention that it needs it sub-frameworks also linked. You can then link these sub-frameworks in addition and it will compile.
This is unfortunately a limitation of Xcode/iOS as it currently stands.

Related

How to exclude a library out of framework when distributing it?

We created a IOS framework which is distributed to various people. But now we came across an interesting problem. We use protobuf in our framework and one of our clients started using Expo Kit which also recently included protobuf and now our client gets a crash with our framework:
Class Foo is implemented in both ... One of the two will be used. Which one is undefined.
We can't use the Cocoapods Protobuf-ios because it is outdated.
My only option that I can think of is to build the framework without our protobuf files included for this client. So our framework will then use their Expo Kit profobuf files. How do I go about doing this in Xcode or is there an alternative solution.
Edit:
What I want to achieve but just can't seem to get it right. I want to distribute my Framework without my Protobuf.a file. Protobuf.a must be a dependancy on the client apps.
Have you considered moving to another, more maintained, Protobuf framework like the one from Apple (bonus points for being made for Swift).
https://github.com/apple/swift-protobuf
Hope it helps ;-)
You need to have a dynamic link to the package and avoid embedding 3rd party binaries in your framework unless neccessary.
Checkout these articles, hope they help you:
https://theswiftdev.com/2018/01/25/deep-dive-into-swift-frameworks/
https://www.bignerdranch.com/blog/it-looks-like-you-are-trying-to-use-a-framework/
Also this is interesting one:
When should we use "embedded binaries" rather than "Linked Frameworks" in Xcode?
You don't need to link Protobuf in you client application, if it is already embedding/linking your framework which contains Protobuf.
In you client application, you can provide the path of the Protobuf embedded inside framework. You just need to modify the Framework Search Path for client application and provide the path to protobuf embedded inside the framework.

xcode how to develop with frameworks

Thanks for spending time reading my question.
I've been working as an iOS developer for more than 2 years and today I still feel shame because I don't know how to deal with frameworks. I've build some projects using my own frameworks, but I've never understood exactly what's the best practice doing this.
Lets see the following example:
Project -> FrameworkA -> AFNetworking - Charts - FMDB - more
So, I have a big FrameworkA with mostly all the app behavior and then a small project referencing this FrameworkA and customizing just icons, texts and images. I use to manage dependencies with CocoaPods and I would like to use it with FrameworkA. By this I could reference external libraries easily, but it seems it doesn't work for frameworks, only for projects. So, my questions is: how can I add AFNetworking, Charts, FMDB, etc to my FrameworkA and then reference the framework form my project?
I appreciate if you can give me some idea using CocoaPods or any other dependency manager. I don't like the old way by doing this manually.
I hope my case is clear.
Thanks!
It sounds like you are asking how to embed external frameworks such as AFNetworking into a framework you are developing, and then use that framework in your app.
This is what's known as embedded frameworks where one framework is stored within another. Generally speaking it's not a great idea and should be avoided because it can cause version clash issues.
The way I'd recommend doing this is to use CocoaPods or Carthage to link the external frameworks (AFNetworking, etc) into your framework project. But do to try to embedded them.
Then in your app project, again use CocoaPods or Carthage to link in your framework (you won't need to link the external ones unless you are directly using them in the app code). Then add the necessary build steps to copy both your framework file and all the external framework files to the finished app's framework directory.

Can I make iOS all-in-one framework? or include private static library into my framework?

I'm a novice on XCode and I'm making an iOS Framework with Swift2, including 3rd party libraries(*.a) and frameworks.
I want to provide it as API to others, but I also want to hide the 3rd party libs and frameworks files from my framework distribution files because they are private.
Therefore I just want to open API interfaces and classes I defined.
Is it possible? How to configure my build options?
You can do that but there are some things you need to consider:
You cannot embed one framework into another one. That means if you do not have the sources to a particular framework you have to ship it alongside your own framework. If you have the sources you may consider compiling them into your framework directly.
Depending on the sources that you use in the framework you might have to do some post processing of the framework to obfuscate private headers etc. For example, if you use Objective-C or C code alongside Swift you definitely need to do some post processing of your *.framework file to hide any API that you want to keep private.
If you use Swift code in your framework please be aware that your framework can only be used by someone with the same Swift compiler version due to the absence of an ABI. That means binaries produced by one compiler version have a high likelihood of being incompatible to a newer version of the compiler.
Static linked libraries can be linked and therefore "merged" into your framework binary directly. You just need to make sure that you have a compatible binary for the architecture you want to target, e.g., you cannot use a static linked library that was build for simulator and link it against your framework that you want to build for the actual iOS device.
If you use Swift in your framework, the users of your framework need to include the Swift dylib libraries in their app bundle - either by using Swift in the app or by enabling the Embedded Content Contains Swift Code build setting.

Embedded Binaries with iOS Framework

I was able to create iOS Framework for Xcode as shown in that video:-
https://youtu.be/86cPaa3FrRg?t=4m55s
On 5:00 they say that framework must be added to Embeded Binaries.
If I add it to Embeded Binaries then it works.
It is not required to add GoogleAds.framework to Embeded Binaries.
Adding to Embeded Binaries looks a bit "hacky" comparing to Googles solution.
So I think this tutorial is missing some step.
My question is: How can I make a framework that works without adding it to Embed Binaries?
tl;dr They are both frameworks, but they are different types.
The term "framework" is ambiguous. On OSX it means a packaged dynamic library (i.e. .dylib, headers, other stuff), however before iOS 8 users could not create dynamic libraries so "static frameworks" were invented to provide packaged static libraries (i.e. .a, headers, other stuff).
If the framework you created needs to be packaged with the app as an embedded binary then it sounds like a dynamic framework, however if Google Ads doesn't then I suspect it's a static framework. It doesn't need to be embedded as it's already been linked into the app binary.
If you want to know how to create a static framework, then start here, or Google for "ios static framework".
Prior to iOS 8, developers shipped unsupported frameworks that were cobbled together with static libraries by mimicking the directory structure of Apple's frameworks. They worked, but they were a pain to build, and they were static—not dynamic—libraries.
As of iOS 8, Apple officially supports building third-party dynamic frameworks in Xcode. These types of frameworks are code-signed and must be placed in the Embedded Binaries for your app. If you link against them but fail to put them in Embedded Binaries, you will get an exception when attempting to run on device and your app will crash.
In the long-run, I would expect the hacked together frameworks like GoogleAds.framework to disappear now that official framework support is available. This means you'll have to get used to putting frameworks in Embedded Binaries.
Unless you need to support iOS 7 with your code (in which case official frameworks are not an option, because they only work on iOS 8), I would advise against creating an unsupported type of framework at this point.

Does iOS 8 support dynamic linking?

Up until iOS7, Apple did not support dynamic linking due to security concerns. Code reuse between developers usually relied on static libraries, which were built as part of the executable of the app.
Introducing extensions in iOS8 seems to change this a bit, because extensions are separate executables. Sharing code between an extension and its containing app is done via a framework. Apple is saying this in their release notes:
Frameworks for iOS. iOS developers can now create dynamic frameworks.
Frameworks are a collection of code and resources to encapsulate
functionality that is valuable across multiple projects. Frameworks
work perfectly with extensions, sharing logic that can be used by both
the main application, and the bundled extensions.
Emphasis is mine.
Source: https://developer.apple.com/library/content/documentation/Xcode/Conceptual/WhatsNewXcode-Archive/Articles/xcode_6_0.html#//apple_ref/doc/uid/TP40014509-SW14
Further, in the extension dev guide, they explain that you can share code between an extension and the containing app via a "embedded framework".
Source: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1
My question is - what is an embedded framework, how does it differ from a dynamic framework, and will we really see proper dynamic linking in iOS8? All the documentation I've read seems ambiguous about this.
"Embedded" and "Dynamic" frameworks don't refer to the same aspect of frameworks. They are not the opposite of one another. First, let's define what's a framework: in Apple lingo, a framework refers to some compiled code + the public headers of said code.
Now a dynamic framework is a framework whose code was built as a dynamic library. It is the opposite of a "static" framework, where the code would be built as a static library. In case you're wondering, Wikipedia has a very nice explanation of what's the difference between a static and a dynamic library.
And finally, an embedded framework is a framework that is packaged within an app, as opposed to being installed system-wide, in "/System/Library/Frameworks" for example.
An embedded framework is simply one that's included in the app bundle, rather than a global framework which is installed in system directory.
Dynamic Frameworks doesn't means dynamically linked framework. Apps still just work in a sandbox environment. It's not like your custom frameworks are going to be installed with the iOS. Each one of your apps that uses the common framework that you've developed is going to be copied inside every app's bundle.
You can see this for yourself. Go to your Xcode's Derived Data directory and inside the app's data, you'll find all the embedded frameworks copied.
The only new thing with creating Frameworks with iOS 8 compared to static libraries is that the public header files and assets gets bundled within the Framework. If you've been doing this sort of things with earlier versions of Xcode, you'll remember the pain with supplying public headers and then adding the search path within Xcode settings and for assets we had to pass in a separate bundle.
This only downside of using Frameworks that I see is that now we can't simply use lipo to generate a fat static library for all kind of architectures.
IMO Apple is using the word 'dynamic' to suggest 'independent'.
Watch WWDC2014 - Building Modern Frameworks for more details.

Resources