This is the second part of a two-part article on how to create and use static library projects in your iPhone apps. In Part 1, I discussed how to create a static library project, as well as including a test application.
In this part, I will describe how to include this static library project into other projects. The steps outlined here offer several advantages. One is the ability to load the static library project simply by double-clicking on the project reference in your other project. This brings up a new Xcode window for the library project, where you can browse the code and even make changes. If you do make changes in the static library code, not to worry because when you build your application, it will also build your static library project.
In order for this convenience to work, though, you must follow these steps closely. Xcode is powerful, but it is also non-intuitive and finicky in some areas.
In this part, I will continue my example of using my BackgroundTask static library I put together in the first part. This static library is available with its project and source code at the Osmorphis group. I will be "importing" this library in another project I am working on that needs the BackgroundTask functionality.
So let's begin!
Bring up your client project, the project that wants to use the static library, in Xcode. To bring over the library project, all you need to do is drag the project over. You can do this one of two ways:
In this part, I will describe how to include this static library project into other projects. The steps outlined here offer several advantages. One is the ability to load the static library project simply by double-clicking on the project reference in your other project. This brings up a new Xcode window for the library project, where you can browse the code and even make changes. If you do make changes in the static library code, not to worry because when you build your application, it will also build your static library project.
In order for this convenience to work, though, you must follow these steps closely. Xcode is powerful, but it is also non-intuitive and finicky in some areas.
In this part, I will continue my example of using my BackgroundTask static library I put together in the first part. This static library is available with its project and source code at the Osmorphis group. I will be "importing" this library in another project I am working on that needs the BackgroundTask functionality.
So let's begin!
Bringing over the static library project
Bring up your client project, the project that wants to use the static library, in Xcode. To bring over the library project, all you need to do is drag the project over. You can do this one of two ways:
You can drag the whatever.xcodeproj file (it is really a directory) from the Finder. This is the file to drag over:
The other option is to drag the project from one Xcode window. This is the root element of the Groups & Files tree:
Where you drag this is the Xcode project of the application that wants to use the library. You can drag and drop anywhere in the Groups & Files tree. When you drop, a dialog sheet comes down asking for the details of what you want to do:
Be sure you do not select "Copy items..." and the reference type is selected as "Relative to Project".
What you'll see after this is a new item in your Groups & Files tree with the same blue "A" icon for Xcode projects. Here is an example of my application that has several static libraries referenced:
If you have many of these, you could group them in a folder called "libs" or something like that.
Specify the Product
Now you have to tell Xcode what products from this external project you are interested in. Select the library project you just dropped in. If you don't see the "Detail", "Project Find", ... tabs, then you may have your editor window taking up the entire content pane, so drag down the split pane to show:
As shown above, you want to select the library product, but not the test app.
Locate Header Files
You need to tell your application where to find the header files of the referenced library. It would be nice if the reference would be sufficient, but it is not, so you have to muck with compile flags.
Double-click on the project of your target application. Important: don't click on the root element of the Groups & Files tree. This is not what you want. You want to click on the application in the Targets element of the tree. If you edit the wrong one, you'll be banging your head on the wall for hours with missing header file problems (like I did).
Go to the "Build" Tab.
Make sure you are editing for all configurations, since the location of the header files won't change, if you use the instructions below.
We need to edit the "User Header Search Paths" property, so go ahead and start typing this in the search box (or you can hunt for it manually). Double click on the value field. This should bring up a dialog that may contain other entries.
Add a new entry for your static library. The public header files are stored in a long-winded location, and it depends on whether you're building a Debug or Release build, and if you're building for the simulator or an actual iPhone device. These specifics are encoded in some variables. So copy and paste the following for your new user header search path:
${PROJECT_DIR}/../staticlib_project/build/${BUILD_STYLE}-${PLATFORM_NAME}/usr/local/include
Replace the "staticlib_project" part with the directory of the static library you are trying to set up. This assumes that your static library project is in a peer directory.
I have several static libraries referenced in my application, so my user header search paths property looks like this:
The ${BUILD_STYLE} and ${PLATFORM_NAME} variables will be replaced automatically to match your current build. This is how we can use the same settings for all builds.
Setting Linker Flags
While we're in the build properties, we need to add an option to the linker flags: -ObjC. This tells the linker to load all classes and categories from static libraries. If you don't do this, then you may get linker errors.
Clear out the "user header search" in the search box and type "other linker flags". Add -ObjC to this:
Set the Dependency
Now we would like to set a dependency on the library so that it will get compiled when you compile your application. Double-click on the application under Targets, and go to the "General" tab.
Click on the + button for the Direct Dependencies. Select your new library.
You also may have to add the library to the Linked Libraries panel, also found on the "General" tab. Hit the + and select the library. I have seen times where the library is not available to choose. In these cases, drag the .a file from the project down to the "Link Binary With Libraries" section of the target.
Good to Go
At this point, your static library should be properly referenced. The nice thing about this setup is that your library is built whenever something is changed; no need to switch over to that project to build it separately. But, if you need to look at the source code, simply double-click on the project from your tree and the other project is opened up in a new window.
It is also to step into the source files of your referenced libraries in the debugger.
So stop dropping copies of reusable code into your projects. Build a library and reference them!
Thank you very much for this post (and for part 1 as well). Following your clear, well written instructions, I was able to get up and running with static libraries in no time at all.
ReplyDeleteRobert
Great step-by-step! Do you know of a way to have a resources bundle (images and sounds and such) with a static library?
ReplyDeleteI don't think you can bundle resources with a static library. This is a feature of frameworks. I googled this and couldn't find anything. If anyone knows how (besides the obvious manual copying of resources), please let us know.
ReplyDeleteNice how to, it helped a lot. The latest XCode has a template for creating a static library in one step now, which makes life simpler.
ReplyDeleteI did run into a problem linking my static library. The library requires some frameworks, e.g., MessageUI.framework, that my app doesn't need directly. I've included those in the library. However, the app doesn't see them and compilation produces linking errors. I had to include the frameworks required by the static library in the main app to make the errors go away. Is there a way to get around this? Thanks
Thank you so much!!!
ReplyDeleteI have done all Steps of Part 1,Part 2,then also it is showing error when I am going to use library.
ReplyDeleteHi JES,
ReplyDeleteI tried to add a REST Client, just the way you have explained and my project is building without any error. But for some reason I cant import the header files of the static library. I tried with all possible ways, but no luck. :(
FYI.. the REST client lib is : https://github.com/jeremylightsmith/RestClient