XCode - Adding a external static library in Cocoapods project - ios

I am experimenting with the Cocoapods to understand what settings/configurations it does so everything works so smoothly. While doing that one specific case troubling me.
Basically there is a different behaviour between non cocoapods projects that uses external libs and cocoapods projects that uses external libs.
Both projects and external library can be found on GitHub.
1) External library libImageFilters.a uses CoreMotion framework. So finally when this library will be included in any app, that app will either include CoreMotion framework or use clang modules so that just by doing #import CoreMotion; framework is added. I prefer the second approach and for this in the header file (ImageFilters.h) added below lines
#if __has_feature(modules)
#import CoreMotion;
#endif
2) AppWithoutPods application just add this external lib and header file. Do the below settings
Enable Modules = YES
Link Frameworks Automatically = YES
Build the application and everything build fine as CoreMotion Framework is included through header file.
3) AppWithPods application uses AFNetworking as a pod. So install the pods and open workspace. When built with above clang module settings,everything builds fine. Now if I add external lib and header file. Build fails with linker error saying CMMotionManager is referenced from libImageFilters. When CoreMotion is explicitly included it builds fine.
This is where the confusion is. Modules are enabled and frameworks are linked automatically. Basically there is nothing different in both apps except cocoapods.
I checked all the settings for both projects, nothing is different then why build fails? Can someone help me understand this?

Related

Framework missing from System but not XCode on Mac/iOS

I'm working with a Qt project on a Mac. I have to add a framework
MessagesUI.Framework
to the XCode list of frameworks each and every time that I open the project or try to archive it. Is there a way to keep it as a required default so I won't have to add it every time?
I've tried changing the search path but that doesn't seem to work, and it is included in the project files that its used in, within Qt.
#import <ContactsUI/ContactsUI.h>
#import <MessageUI/MessageUI.h>
I also have it linked directly within the .pro file - another framework is successfully added that way.
INCLUDEPATH += /...File/Path.../System/Library/Frameworks
QMAKE_LFLAGS += - /...File/Path.../System/Library/Frameworks
LIBS += -framework ContactsUI
LIBS += -framework MessageUI
UPDATE: It appears that MessageUI.framework is missing from the System frameworks, but not from the XCode frameworks. ContactsUI.framework works, no issue there. Looks as though XCode won't allow me to add a framework from the XCode files, only from System files. ContactsUI.framework was also causing a problem prior to adding its address to the .pro file, but IS in System frameworks.
Use Cocoapods for adding frameworks in Xcode project. This is mostly used way for developers. Here is the link how to use it. Click Here
Cleared Derived Data and discovered a few small (but major) spelling mistakes.
Cocoapods was not necessary to solve this problem.

Xcode: create Framework with pod dependecies

I create a framework that use AFNetworking (installed with pod).
I can import this framework on my project and I can use all classes/methods that I exposed, so project compile.
When I try to run project on simulator, I obtain this error:
dyld: Library not loaded: #rpath/AFNetworking.framework/AFNetworking
Referenced from:
/Users/.../Library/Developer/CoreSimulator/Devices/F56F98F0-2AE0-4C87-AC9A-6E3B449762D1/data/Containers/Bundle/Application/BFA5359F-8FCE-4402-8487-CD9C002CB673/MyProject.app/Frameworks/MyFramework.framework/MyFramework
Reason: image not found
I already included 'MyFramework' under:
Build phases -> Embed Frameworks
I suppose I missing something on building Frameworks, but I can find out what! I already seen this unanswered question.
Who can I use MyFramework without installing Pod on MyProject again?
It is really delayed, for this issue but I have got my project working. It might not be the best way but it works. I am putting it here for future reference.
I wanted to do it without using Pods in the main project. The reasoning is, we are bundling our SDK into a framework.
So essentially, the first step I took was to get the framework project bundling without using the workspace. I just dragged the Pods project into the framework project.
Then I added the frameworks the the pods project creates and add them to my framework. I set them to optional and code sign. You can see them in the picture of where I added them under the build phases.
Then add them to your main project. not the framework the normal way by adding the project and or the framework. Then add it to the Embedded binaries and Linked Frameworks.
If it helps anyone, the solution mentioned by #ArtyomDevyatov does work. The trick is that you have to add 's.dependency' in podspec file.

Embedding frameworks inside closed-source Swift framework

Our company wants to distribute a closed-source SDK for iOS to our clients. I've been using Cocoapods to build the framework and built an example app making use of it. Previously the app worked fine on the simulator as well as when deployed on the device. However, I was also embedding the Pods.framework file in the app itself. One other piece of information that may be of interest is that the framework is written in Swift, the included cocoapods dependencies are both Swift and Objective-C.
I wanted to make the pods requirements easier to manage so the user doesn't need to be concerned with them and tried to embed the Pods.framework file inside of the SDK we're building - so I removed the steps to Embed Pods Frameworks and Copy Pods Resources from the example app, leaving them only in the framework, I also removed Pods.framework as a dependency of the example app, leaving it only in the SDK. This seemed to work in the simulator, but the app now crashes on mobile device with dyld: Library not loaded error.
Upon researching it, I stumbled into a few related discussions:
https://github.com/CocoaPods/CocoaPods/issues/344 https://objectpartners.com/2014/06/25/developing-private-in-house-libraries-with-cocoapods/
However, the suggested solution of using private pods does not look like it would work for us, it's my understanding that the source code in the private pod would still be open, and we can't share it with our clients.
Could someone advise on a solution that would work in this case?
OK, I finally have a more durable solution. It's a modified, cleaner version of my old one now that I understand how Xcode links in my Swift sub-frameworks better
Problem that makes distribution/compilation a bit ugly:
Since Swift standard libraries aren't bundled on the device like Obj-C, nor are they guaranteed to be stable between versions yet (stable binary interface promised in Swift 3: https://github.com/apple/swift-evolution#development-major-version--swift-30) we have to make sure the entire project is compiled against the same version of Swift. That means the guy using your closed-source framework has to be using the same version of Swift in their Xcode for their project as you did for compiling the library, even if he's not using Swift in his code because ultimately it's his version of Swift that gets bundled into the app and your SDK runs against. This is only an issue for closed-source frameworks because open-source ones will always be compiled against the same version as final project. Possible workaround is to restrict clients to same version you use or distribute multiple compilations (i.e. Swift 2.1 and Swift 2.0). To remedy this, you could provide users with copies of binaries compiled against multiple versions of Swift.
Aside from that, here is what I had to do during compilation/distribution to make a binary framework that works in Swift:
When building the framework:
In project target, make sure to add Pods.framework to Linked Frameworks and Libraries (make sure this is a pre-compiled RED version of Pods.framework, I had a black compiled Pods.framework in the same directory which built fine but then resulted in a framework that would cause the project to complain about missing armv7 architecture during linker phase in later project)
In Build Settings, under User-Defined section, add a field called BITCODE_GENERATION_MODE and set it to bitcode
DO NOT #import any frameworks in your bridging header, all instructions telling you to do that are leftover from Swift 1.0-1.2 days, you don't need it anymore and it does more harm than good (the later project will complain that it can't find these headers that aren't even exposed to it)
Change build target to Generic iOS Device, Archive and Export the framework
When building the project using the framework:
Drag and drop the framework into the project, in General tab add it to Embedded Binaries and Linked Frameworks and Libraries (you only need to add the framework itself, not the sub-frameworks or the pods file)
In Build Settings tab, add a new path to Framework Search Paths: $(PROJECT_DIR)/MyFramework.framework/Frameworks
Build the project

iOS8 framework library linking WITHOUT Pods

Imagine the following scenario;
I'm developing a cocoa touch framework that requires SomeLibrary (e.g. AFNetworking). My framework is going to be included into someone's project that might require SomeLibrary as well.
How do I accomplish this without running into these nasty duplicate warnings when I include AFNetworking into my framework directly (either via source code or Cocoapods)?
I've tried it with Cocoapods on both projects (my framework, and a test project that includes my framework), but that results in duplicate code warnings as well.
When I don't add AFNetworking into my framework development project, the compiler can't find the required files, which is why I can't build it. I've tried with including AFNetworking's source code directly into the main project, and using the pod, but in both cases the AFNetworking/AFNetworking.h import in the framework project fails.
How can I do this without making a pod out my framework (which isn't really an option)?
I've found this related answer, but I don't know what search path to set for the framework project in order to find a library of the master project;
https://stackoverflow.com/a/23123725/1069487
Any help would be highly appreciated!
You will have to build your framework linked against static library.
You build AFNetworking as a static library (that will give you a .a file as AFNetworking.a)
You build your framework that link against your static library. But be aware that the library won't be embedded in your framework (there is no way to include static library into framework on iOS). Your framework is able to use AFNetworking API because it is linked against it.
any project that use your framework and use AFNetworking methods of your framework need to link with the static library AFNetworking.a that you should provide as a standalone file beside your framework.
See iOS-Framework here for more details : https://github.com/jverkoey/iOS-Framework

handling dependencies for iOS Framework project

I've created iOS Framework project using this method: https://github.com/jverkoey/iOS-Framework
Works pretty neat but I'm a little confused on how to include libraries/frameworks that are needed by my framework to work and, in particular, how to do it so that in case 3rd party client app that uses my framework can include these libs as well without conflicts.
Let's say my framework code needs these two things:
FacebookSDK.framework
libFlurry.a
The first one is an iOS Framework. When I add it to "Link Binary With Libraries" phase in my Framework and try compile the client project that uses my framework the linker complains about missing symbols - I need to add FacebookSDK to the client project which is great: there is no possibility of conflicts if client apps wants to use Facebook.
However when I do the same with Flurry static library I get duplicate symbols error when compiling client project. Which confuses me a bit, because isn't FacebookSDK.framework just a packaged static library?
ukaszs-iMac:FacebookSDK.framework lukasz$ file Versions/A/FacebookSDK
Versions/A/FacebookSDK: Mach-O universal binary with 3 architectures
Versions/A/FacebookSDK (for architecture i386): current ar archive random library
Versions/A/FacebookSDK (for architecture armv7): current ar archive random library
Versions/A/FacebookSDK (for architecture cputype (12) cpusubtype (11)): current ar archive random library
So my questions are:
why a library embedded in framework (like Facebook) is not linked to my Framework project product, whereas library included as .a file is?
how to include .a file in my framework so that it does not produce duplicate symbols error when client app using my framework also needs this particular static library?
For the use case you are describing, you should be linking to these external libraries from your application, NOT your own framework. It can be one or the other, but it can't be both.
If you decide that these dependancies belong as the responsibility of the application, you would remove them from "Link Binary With Libraries" and any other explicit linking configuration, and just project your framework project with the path to these frameworks and libraries so it can find the symbols (but not link against them) at compile time (i.e. the path to the libraries should be included LIBRARY_SEARCH_PATHS).
Use cocoapods , it's easy (http://cocoapods.org/)
Your application developers will have to include the podfile and download the dependencies.
While developing your SDK use a reference application/demo app on top of the SDK to simulate this.
You shouldn't link anything when building your framework but just create a *.a binary with your framework's objects.
Also you should not include code from other libraries in your framework as client applications may be adding the same libraries directly or requiring different versions of them, thus creating conflicts.
Off course you can reference *.h header files from other libraries in your framework in order to compile your objects.
As a result the installation steps for your framework should detail other required frameworks/libraries needed, their supported versions, how to add resource files (if any), etc. Just some of the many reasons why you may want to consider Creating a CocoaPods' podspec instead.
You should use CocoaPods. Your dependency on Facebook can be done by linking against the CocoaPod.
If you want to include that particular version of Facebook in your pod, you can put it in your repo and use the vendored_frameworks property to refer to it.
Similarly if you wanted to vendor libFlurry.a, you could do so using s.vendored_libraries.
For system libraries, you don't need to vendor them, e.g. libZ.a.
I strongly recommend creating your CocoaPod using pod lib create YourPodName. They've recently changed the mechanism for how this works and it's really nice.
You can create an Example project that shows how to use your code in context of an app.
Then one of the other neat things I just learned about, someone can do pod try YourPodName and it will automatically download, integrate and run the Xcode project.
CocoaPods is worth the trouble.
I am building my framework project using CocoaPods.
The framework uses some 3rd libs from CocoaPods.
Podfile specifies to install dependency on target of the framework.
When I build the framework, it includes all libs in the binary.
If I add use_frameworks! in Podfile, when the framework is built, it will not include 3rd party libs.
Use CocoaPods dependancy manager. Here's a good guide,
7 miniute video tutorial
Mostly if you install third party frameworks you can install with cocoapods (which is really nice, I would definitely do that) or they offer you to download the framework and include it in your Project.
If you decide to download the library and include it there is normally a list of frameworks you need in the "Getting started" guide.
Means: Offer them to install using cocoapods and to download your library but do not include anything else, give them a list what they need.

Resources