Handle complex iOS projects with multiple dependencies

If you are reading this post I’m assuming you are having an hard time and tons of errors from xcode trying to compile third party libraries into your project.
I had my hard time me too! I wrote this little “tutorial” after a whole day of build failures, warnings, tests, google searches, configurations, git clone, svn checkout… and a lot of stress! I hope I will help you saving time and reach your goals, good reading ;)

To include a third party library into our iOS projects there are fundamentally 2 ways. The first, and the simplest, is to include the raw sources (headers and implementation files) into them (using drag and drop or “add files to” from the contextual menu), once done we are ready to go after a simple build. Anyway this is not an ideal solution, because in a scenario in which we have several projects all requiring a particular library, we should copy/paste its sources for each project and moreover we should update library’s sources manually every time it will get updated (in the git/svn repository by the “vendor”)!
The second and the best way, is to manage libraries we will depend on, as sub-projects and linking against them. Here is a brief to-do-list:

What to do

1. Each dependecy should be an xcode static library project, that is an .xcodeproj with a target of type library (“.a“) rather than application (“.app“). In most cases third party libraries are already configured in this way and ready to be imported (step 2)

2. Each project must be added as a sub-project to the main project. You can do this by selecting the main node in the folder tree (that one with the blue icon reporting project’s name) and adding the .xcodeproj file using “add files to...” from the contextual menu (DON’T CHECK “Copy items into destination…” because we are going to create a reference to it not a copy of it!)

3. All the static libraries must be linked to the main project: go to the Target’s “Build Phases” and add the library (.a) in “link binary with libraries

4. The main project should specify all the paths where subprojects headers are located (“header search paths” in Target’s Build Settings).

An absolute path is the best way to speciy this paths, in my case: “/Users/davidezanotti/Documents/X_CODE/CoolLibrary”


If the headers are located under different subfolders (ie: /CoolLibraryPath/headerFolder1/, /CoolLibraryPath/headerFolder2/…)
you can specify just “/projectPath” and check “recursive” to automatically scan each subfolders for .h files, otherwise if they are in a specific folder like “/CoolLibraryPath/src/Classes/” and you don’t want a recursive search, be sure the path string ends with “/”

5. If a project we are referencing to, makes use of particular frameworks (UIKit.framework, SystemConfiguration.framework, Security.framework…), the main project must use these frameworks too. So we have to include them in Target’s “Build Phases” (under “link binary with libraries“)

How to prevent errors:

1. The main project should specify the following flags “-ObjC -all_load” in “Other linker flags” (under Target’s Build Settings). These force the loading of all headers and categories.

2. All subproject should expose their header files as “public”

3. Read CAREFULLY (word by word) instructions that come with downloaded libraries and ensure you did exactly what they say

4. Check CAREFULLY each path typed

5. Pay attention to typo errors

What to do when build fails:

It depends on what type of error(s) has occurred, anyway in 99,9% read again “What to do” and “How to prevent errors” until you will compile. Don’t be fooled by the error message, because it’s often inaccurate and misleading. For example a message like “undefined symbol for architecture i386” may tempt you play with architectures settings when the problem is completely different.
If after several attempts you are still unable to compile the project with its dependencies and you are unable to find the answers on google, try to create a new project from the scratch, add your original classes and assets and then add libraries one at time.

ps. In some case I had to change some import from to “Foo.h” to compile all the projects successfully

Special case: JSON framework

This framework (available here: https://github.com/stig/json-framework/) is used by several libraries, that unfortunately had adopted it by simply copy the sources into the project (first way). The result is that I was unable to compile my project because I get “duplicated symbol” errors because I’m using a couple of them. To solve my issues I cloned the original git repository, added that project into mine and under Target’s “Compile Sources” section of these libraries I removed .h and .m files of the JSON framework. The final result is that I left untouched the downloaded libraries (the files are still where they were), but I can compile without problems because now I don’t have duplicates, all the sources are retrieved from the JSON project once rather than one time for each sources in the library!