Conflict between static libraries used in Xcode project - ios

I am using RestKit, GData and Facebook API.
All of them has a JSON files, many of them share the same name, enums etc.
When i compile I get an error on duplicates.
How can i prevent the conflicts?
Thanks
Shani

This is my best guess. It would be helpful to post the errors you get on compile.
If you are using the -all_load linker flag, turn it off. If your libraries require that you use this option, try using -force_load option on the specific libraries that require it. As an absolute last resort, build the libraries that you can from source, renaming colliding symbols.
The question below might provide some more insight on the all_load issues:
Objective-C categories in static library

I ran into this issue because the new Facebook SDK 3.0 is now a static framework which also includes SBJSON, I also have another static framework which also includes the same class. Originally I would just go in and edit the source files of the Facebook SDK and apply a custom prefix to the SBJSON classes. This no longer works.
Here is an outside the box solution.
Navigate to FacebookSDK.framework->Versions->Current
Open the compiled FacebookSDK library file with the best IDE, textedit will do!
Search case sensitive and replace all occurrences of "SBJson" with "FBJson"
Search case sensitive and replace all occurrences of "SBJSON" with "FBJSON"
Save, clean, compile.
Note: Some would say, why replace with FBJson and not FBSBJson? I determined it would be best to keep it the same character length to be safe.
Note: If you are attempting this with other frameworks, be sure to search the header files for any references to the conflicting class that you are renaming. In this case the class being renamed was not referenced in any of the header files. If it had been, I would have made sure to rename it in the header files.

Related

How to combine fat static libraries for use in an iOS application?

I got very confused when reading about static libraries and dynamic libraries and then finally about frameworks, Cocoa Touch Frameworks and Cocoa Touch Static Libraries.
The only thing I understood is that static libraries (frameworks?) are added at compile time, whereas dynamic libraries aren't; they're loaded dynamically during runtime.
Q:
I'd like to add several static libraries (they end with ".a", universal fat binaries, compiled for a bunch of iOS architectures such like armv7 and arm64) to my iOS application. Preferably, if possible, that'd be done by combining all of those libraries together (...to a framework?).
I also want to write a Swift wrapper around those C libraries. This wrapper shall finally be used in my application. However, the wrapper shall not be part of my app, I want a separate project (again, a framework?) for that (can the libraries and the wrapper be combined together?).
What I'm currently trying to do is to write the Swift wrapper.
So I've started with a Cocoa Touch Framework (because I thought that would be the best idea), added the C libraries and headers (actually via a podspec, I don't think that matters though as I could also add them manually), added a bridging header (although some other users reported frameworks don't work with bridging headers, mine does build successfully). Is this the correct way to go?
The first article I read was this one (called "Static and Dynamic Libraries and Frameworks in iOS").
Then, I read lots of articles on stackoverflow about how to compile static libraries, how libraries & frameworks are structured, that frameworks are really just a bundle of libraries and their headers (or so).
I also feel like things have changed over the years at Apple, like they changed the names and possibilities (the Cocoa Touch Framework (is that a dynamic framework?) seems to have been introduced on the release of iOS 8 etc.), which made it even more difficult for me to understand how things work.
Don't get me wrong, I'm just saying this because I want to make clear that I have indeed done some research (quite a lot I think), but I really need some help to get everything right. Basically, I'm just looking for the next step I should take in order to import all those libraries to my app.
There two parts to this:
Creating the framework Mach-O image
Sorting out the headers
The first part should be relatively straightforward. If you create a framework target and add a bunch of static libraries to it, the resulting framework will include all of those static libraries.
The only complication is Objective-C. If any of your static libraries contain Objective-C code, the linker may end up stripping that out. There’s a linker flag, -ObjC, that disables this.
Sorting out the headers is a bit more challenging. Frameworks have their own view of how headers should be organised, and this generally doesn’t line up well with UNIX traditions (which is what you seem to have). The critical question is how your client code uses these headers. If the client code does stuff like:
#include <lib_1/----1.h>
you have to preserve that layout on disk, and there’s no obvious way to do that when working with a framework. OTOH, if you have control over the client code, and can change it to just do this:
#include <MyFramework/MyFramework.h>
you could create an umbrella header in your framework, have it include all of your public headers, and away you go.
This answer was copied from the Apple Developer Forums.

Converting an Objective-C framework to Swift - Header files still displaying Objective-C functions

I converted my entire Objective-C framework to Swift. After building it, when I check the framework's Header files, it is still displaying the old Objective-c functions.
I deleted all the Objective-C files from the framework project. I have tried cleaning and building the project. But with no success.
You deleted the Objective-C files from the Xcode project, but did you also remove them from the file system and any source control you might be using?
Also, your Build Settings in your Xcode project can be searching for library/header files even after you've removed them from explicit inclusion in the Project Navigator in Xcode.
Just make sure the search paths don't look for old Obj-C stuff. Be careful of recursive searches like MyXcodeProject/**. The ** will recursively search all subfolders and their subfolders for things to include.
Better to specify folders directly in the search paths if you can. If you know you don't need search paths, you can just clear them all.
...although, you may want to leave the default exclusions in place:
Remember that you can't subclass a Swift class in Objective-C.
Therefore, the class you migrate can't have any Objective-C
subclasses.
Once you migrate a class to Swift, you must remove the corresponding
.m file from the target before building to avoid a duplicate symbol
error.
To make a Swift class available in Objective-C, make it a descendant
of an Objective-C class.
Command-click a Swift class name to see its generated header.
Option-click a symbol to see implicit information about it, like its
type, attributes, and documentation comments.
from: https://developer.apple.com/documentation/swift/migrating_your_objective-c_code_to_swift
Also, delete your DerivedData, do a clean build and restart the xCode.
How can you see "Header" files in Swift based framework even after removing Obj C files. Definitely there's the build issue. If build is proper, then you are not referring/using to the right framework (in the app) after building it. This is most common mistake that I observed with many developers.
Maybe this can help, try it on your framework's Target Build Settings:
Disable modules (Enable modules (C and Objective-C))
Make sure the Swift version is set (Swift Language Version)

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...

How do you compile a static library that has a 3rd party dependency without including the dependency?

TL;DR
How do I build a static library without including a third party library that I'm referencing?
Hi,
Before I begin, I know how to compile a static library in Xcode targeted for iOS devices and simulators. However, this time around I have a dependency on a third party library that I do not want to include in the static library. I simply want to reference it. However, whenever I am building my static library I get a lexical or preprocessor error, which I know is common when the library is missing from the project. The error occurs because I removed the library from the project, because I didn't want to have it built into the static library.
The library in question is AFNetworking. I will be using CocoaPods to explicitly have the dependency installed when installing my static library.
Thank you.
When you reference external code, you will always need to have the headers accessible by your project, otherwise the compiler wouldn’t be able to tell you if you are referencing the external code in a proper manner. E.g. does the method exist, are you providing the right types, etc.
The duplicate symbol problem only exists when you actually define a symbol multiple times. For instance, defining class related Objective-C symbols only happens in a #implementation...#end block, not in a #interface...#end block. The latter is only for the compiler to make sense of things.
(This is also why you can define a #interface for e.g. a private class and use it as normal and not cause duplicate symbols.)
Therefore, you can include such ‘clean’ headers multiple times without having to worry about it. Note that I said ‘clean’, because you can actually define symbols in headers by, for instance, defining C functions in headers or even a Objective-C #implementation, if you feel especially wicked. But you will simply have to test this.
The linker will complain when you finally link the 3rd-party dependency and yours and there were duplicate symbols after all. In that case, be sure to look into tools such as nm which list the symbols in an archive.
you can add the lib.a and lib.h into your project.

Includes fail to resolve correctly in Xcode workspace

I'm having trouble linking to a static library in Xcode 5. I did read the chapter on building and using a static library in the Pro iOS 5 Tools. What it told me to do after creating your static library, was to link against the framework in the Build Phases tab. That part is pretty straight forward. Then it says in the Build Settings, under "Header Search Paths", to add:
$(BUILT_PRODUCTS_DIR)
Then in order to use my static library, I just import it like so:
#import "ConversionCalculator/ConversionCalculator.h"
So this used to work up until yesterday. I tried adding a new static library to my project which didn't seem to work. So I cleaned my project, and tried rebuilding again, but now Xcode complains about #import "ConversionCalculator/ConversionCalculator.h". It says
Lexical or Preprocessor issue. 'ConversionCalculator/ConversionCalculator.h' file could not be found.
I was wondering if anyone has any tips on debugging this. I've looked through different tutorials like this:
http://blog.stevex.net/2012/04/static-libraries-in-xcode/
http://cocoamanifest.net/articles/2011/06/library-management-with-xcode-workspaces.html
http://www.raywenderlich.com/41377/creating-a-status-library-in-ios-tutorial
But I can't seem to find the "golden way" to link to a static lib, or how to troubleshoot why Xcode cannot find my file. My file structure is setup on my machine like so:
Projects\
DistanceCalculator\DistanceCalculator.xcodeproj
ConversionCalculator\ConversionCalculator.xcodeproj
DistanceCalculator.workspace
Like I said, this all used to work too when I followed the tutorial in Pro iOS 5 Tools book. Now I don't know why my workspace cannot find ConversionCalculator when it has used it before. The part I find hard is different articles say different things about the header search path, and I'm not sure what the best way to populate that field is. Any thoughts? Thanks in advance!
Edit:
I'll add that I can build for the device without errors. But when I switch to the iPhone simulator, it gives me that error about not being able to find the file. I also see that I get this warning:
ConversionCalculator was rejected as an implicit dependency for 'libConversionCalculator.a' because its architectures 'i386' didn't contain all required architectures 'i386 x86_64'
Looking at that, I'm not sure what that means. If it means that my library is not being built for all architectures, I just tried creating a Target that builds for all architectures according to the wenderlich article in the above link. That seems to work as when I go to the dervieddata folder, I see for debug, release, and universal, I see the libConversionCalculator.a file. But then when I go back into the workspace and try to rebuild the project for the simulator, I get that could not find file error and the implicit warning.
Edit #2:
I just saw a warning flag on Xcode that says upgrade to recommended Build Settings. Now I get no errors. Not sure what happened... but I guess no errors is good.
I would follow the description available in Xcode's Help topic "Linking Against Your Library" in chapter Configuration Your Application in Introduction to Using Static Libraries in iOS
(you may search within Xcode Help, too).
Except that I would recommend to include your headers from libraries always using angle brackets:
#import <ConversionCalculator/ConversionCalculator.h>
Using double quotes may inadvertently search and find files with the same name in some sub-folder relative to the file where this import directive is written. Only after there was no file in any sub-folder the preprocessor starts searching with the specified header search paths.
Using angle brackets, the preprocessor immediately searches only at the specified header search paths.
So, since you actually want to find headers for the corresponding library, always use angle brackets.
Note: If you follow the recommendation to create a static library project, you don't need to explicitly set a header search path in the target that links agains the library: Xcode will already add a search path:
$(BUILT_PRODUCTS_DIR)/includes
Your library headers are located in
$(BUILT_PRODUCTS_DIR)/includes/<product-name>
which are placed there through the "Copy-Files" phase of the iOS static library target, whose "Destination" is set to "Products Directory" and whose "Subpath" is set to "includes/${PRODUCT_NAME}" per default.
You may change these default settings to other reasonable and sensible values. (if you do, consider the the consequences for Xcode's default search paths!)

Resources