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

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.

Related

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.

How to build an iOS Framework with a dependency on another without creating an Umbrella Framework

I am trying to streamline my development by creating some re-usable Frameworks which incorporate features I commonly re-use in multiple projects.
However, having setup one of my Frameworks I have encountered a problem, the classes have a dependency on the Firebase framework. Having read the Apple docs it's not recommended to create an Umbrella Framework (one which embeds another) especially if you do not have ownership of the embedded Framework (which I do not).
So the question is:
How can I create a Framework project which allows me to build the Framework without including the dependencies which would create an Umbrella Framework. I presume this is what people like Firebase do because when you add their Framework there are others you have to add to your project as well. I can't quite see how you would configure a project to allow you to build the Framework without errors but not include the dependencies.
For reference I am using the latest Xcode and need to support iOS 8 and above.
Thanks in advance for any thoughts / suggestions on this
For the benefit of anyone who is struggling with the same issue, the answer is much simpler than I had anticipated.
The Frameworks are linked dynamically and simply adding a Framework to the project for your own framework will not cause it to be embedded in the output file and therefore not generate an Umbrella Framework. You don't actually need to do anything. Any Frameworks that are required by your own Framework can be included in your project so that you can compile your own Framework, and will also need to be included in any projects that utilise your Framework.

iOS Frameworks, embed another framework or library?

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.

iOS Framework build: what is the best practice to link with third-party libraries?

I'm build a Framework for iOS and my framework has AFNetworking as dependency.
So what is the best practice to include AFNetworing? Reading other posts (specially this question here) i came up with three options:
Copy all the .h.m files from AFNetworing in to my project and compile my framework with it. But according to this, it will possible cause a situation where some third part developer using my Framework are already using AFNetworking and will get a compile-time error that some class is declared twice.
Use CocoaPods and link AFNetworking to my Framework. This is causing this error: -lPods is not an object file (not allowed in a library).
Build something like the Aeris SDK where the third part developer using my Framework will be responsibly to add AFNetworking to their project.
I think that option 3 is the best but i don't know how to do that. How can i dev my framework calling AFNetworking classes/methods but do not include on the final framework product?
Thanks!
That's a very bad practice to use third party library in you library.
Ideally you should avoid doing that.
But if you really need it, you can define and add prefixes to class names.
Refer this article Avoiding dependency collisions in iOS static library managed by CocoaPods
Ok. I decided to go with the option 3.
A just added all the header files from any third-party lib to the my framework project (you can also add the .m files but not include them on the static library target).
And a i also documented everything, so developers using my framework will know what are the dependencies and how to include/install them on their own projects (including third-party lib versions, CocoaPods support, etc).
I decided not to go with option 1 because that will cause some situations where a project will have two copies of the same lib compiled on the final app. Even if a change the namespace for the libs on my framework code (to prevent "duplicated symbols" errors) that will still cause some other possible problems like an APP with larger size, possible bugs related to two or more instances of the same lib running together, etc...

Avoiding header conflicts when creating and depoying Static Libraries in iOS

I have created a static library in iOS where I have certain common functionality for my projects. I used the instructions for the iOS Universal Framework and everything works great.
I have a module in the static library that requires AFNetworking. So I installed the cocoapods, and included it in my static library
However, when I include my static library into another project that also needs AFNetworking, and I run the project, I get a duplicate symbol error for all the common classes.
What is the best approach to avoid a conflict like this?
The best approach is not to include any 3rd-party libraries / frameworks inside your framework.
Here's Apple reference regarding "How to build your own framework". There are a lot of guidelines that will help to build a good framework that will not cause any errors if you'll link it to any project.
AFNetworking is a framework that is application specific, so you should not include it into your framework. You may weakly link your framework to AFNetworking, but you should avoid strongly linking it.
Here's resource regarding weak linking.
For example, if you are using 3rd-party library, you should specify that your framework require user to add dependencies in order to use it.
Here's an example how AFNetworking does it.
Also, check this framework, and it's requirements regarding dependencies in its specification.
The best way to do this (in my opinion) is to underscore the class names to keep them unique.
So let's say your library is called XYLibrary. It will have a bunch of AFNetworking files like AFNetworking.h and AFNetworking.m. Rename those to XY_AFNetworking.h and XY_AFNetworking.m. This should hopefully keep them unique from other instances of that library in another project.
You should do this for any other 3rd party libraries as well.

Resources