Prefix or remove classes from dynamic framework - ios

Dealing with dynamic framework i am experiencing symbol conflicts errors which are best describe here: Symbol collusions with third party framework
The problem happens when third party framework is linked twice - in dynamic framework and in consumer project which use the framework and also import the third party framework as dependency
As i can see solutions for static frameworks which suggest removing classes from framework: Removing classes from static library or prefixing classes Prefix classes static framework i am looking for solution for dynamic framework which have diffrent structure.
How is listing classed performed in dynamic framework? what are the actual files which contain the classes which will be compiled at runtime including third party embedded frameworks?

Related

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

Trying to prepare a single dynamic framework to my customer. My framework (A.framework) uses third-party recognition static framework (B.framework). I can't provide separate A and B frameworks to the customer.
Ideally B.framework should be built and included into my A.framework's binary, so the customer's app will only embed A.framework without any additional actions to link with that third-party app.
What I did:
Added B.framework to the project.
Added B.framework to "Linked Frameworks and Libraries" in the corresponding target.
Built A.framework.
Created a demo application and included A.framework to the project.
Added A.framework to "Embedded Binaries".
Demo app's build fails with message "Missing required module 'B'" (despite the fact that it is used in A.framework only).
Note:
I neither created any modulemap files for B.framework, nor additional run scripts
Making A.framework static is not acceptable because it includes some resources (storyboards, icons and some other files)
Tried to make un-recommended "umbrella" framework but got stuck on loading B.framework's bundle in demo app
Tried to make fake "umbrella" framework by simply copying B.framework inside A.framework, but got 2 problems - huge size of A.framework and Mach-O error while exporting the demo application (because of Mach-O difference between dynamic A and static B frameworks)
Any ideas would be highly appreciated!
UPD 1: This is not about umbrella framework because the proper umbrella framework implementation requires to load sub-framework from bundle which is not good. The fake framework implementation (sub-framework simply copied to umbrella) won't work for release because of different Mach-O values - dynamic and static. Plus fake umbrella framework has a huge size because sub-framework is being fully copied inside umbrella.
UPD 2: Created a small test project: StaticFrameworkTest which has 3 sub-projects:
Demo-application with dynamic framework dependency (framework A) and shouldn't know anything about framework B
Dynamic framework with static framework dependency (framework B) which ideally should be included in A framework's binary.
Static framework B
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.

Xcode links a Third Party framework in my Framework and includes it's symbols

I am building a Framework and the code there uses a Third party framework. When I compile my Framework it seems to contain all the symbols from the Third party framework. If I don't add the third party framework to Linked Frameworks and Libraries I get compiler errors about undefined symbols.
On the other hand, when I add the third party framework to Linked Frameworks and Libraries it compiles fine. However, in a sample app when I link both my framework and the third party one I get the following runtime warnings: Class is implemented in both, One of the two will be used. Which one is undefined.
My question is how do I build my framework with a dependency on another framework without actually linking it? I want to do all the linking on the app level.
I wasn’t able to achieve this behavior building dynamic frameworks. However, as I built my framework as static, the framework compiled fine and did not include third party framework symbols. All the linking with the third party framework has to be done on the app level.
I have seen many questions on stack overflow like this with no definite answer. I hope my finding would help.

iOS framework and separate project have the same framework dependencies

I am creating a framework in Xcode for my iOS app which contains a large set of common classes which are used amongst several projects. Some of these classes have dependencies on other frameworks. However, there are also classes in other projects where I want to use this framework, which share some of the same framework dependencies.
To try simplify with an example:
Framework A: has classes which require Framework B
Project 1: includes Framework A, but has a class which requires Framework B.
I am currently including Framework B in Framework A so that my code will compile. There are two problems:
Once I do this, I can't include Framework B in Project 1, because there is now a duplication of classes.
It sounds like I'm creating an umbrella framework, which is usually discouraged.
Is there a way I can build Framework A in a way that says: "trust these frameworks will be included in any projects that use you, and don't include them yourself"?

linking custom framework to library in xcode

I want to include Microblink's PDF417 framework into my library. Library project compile and work fine but when I use MyLibrary.a file in my application I've got "undefined symbols for architecture armv7" error. Any ideas? Can I include custom framework to library or this isn't possible.
Trojanfoe's answer is correct for your case. But in general, the answer depends on the type of the library inside the framework.
iOS/MacOS framework is a just a collection of a library together with all relevant header files. This makes including the library into other projects much easier, because the whole framework can be included at once, thus eliminating the need to modify linker and header search paths and linker flags.
Library itself can be either a static library or a dynamic/shared library. Framework can contain the library of any type, there are no limitations in that regard.
If the library in framework is static, then all the objects from that library are copied into target product at compile time. If the target product is a static library (MyLibrary.a in your case), additional linking with the framework in the application is not needed, because all the objects are contained in MyLibrary.a
If the library in the framework is dynamic, then objects from that library are loaded at load-time or run-time, not at compile time. Because of that, frameworks of that type need to be linked with end applications also.
In your case, pdf417 framework contains a dynamic library, which means you will also have to include that framework into your end application.
I'm a developer on Microblink's PDF417 SDK. The thing is, we can provide our library in any format. The format we have chosen in our Github repository is an .embeddedframework which contains a dynamic library together with all resource files because that makes including the framework into Application projects very simple. If you have a use case which requires a different format, we invite you to contact us on https://help.microblink.com/hc/en-us
A static library is just a collection of object files (a bit like a zip file without compression or hierarchy) and cannot hold information about any dependencies it might have.
Therefore you have to link the final executable binary against both your library and the dependent framework. The same applies if the dependency was a static library, dynamic library or framework.

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