December 7, 2010

Welcome Back

Welcome back to me, after a long 10 month silence. I have been extremely busy with our iPhone app, getting a new job, moving, buying a house, settling in, etc.

The current excitement is completing our long overdue iPhone app. After nearly 2 years in the making, it was finally accepted into the Apple Store. Check it out, if you’re a Colorado traveler:


I’ve learned a lot these past 10 months, and hopefully I can share some of that knowledge here on the blog. So until next time!

February 21, 2010

Static Libraries in iPhone Projects (Part 3)

This is an addendum to my earlier 2-part article on how to create and share static libraries for iPhone projects. Part 1 discusses how to setup Xcode to create a static library target. Part 2 discusses how to share a reference to that library from within another project.

This addendum to address a missing step from part 1. According to Apple documentation, static libraries do not need to be code signed. This is only important if you are an "official" Apple iPhone developer ($99/year).

To remove code signing, select the library target under Groups & Files > Targets. Double click the target to bring up the info dialog window. Select the Build pane.

Scroll down to the Code Signing group. It should look something like this:

See the highlighted line and how it says "iPhone Developer"? Click on that value and you will get a little menu. Select "Don't Code Sign".

That's it!

February 8, 2010

Static Libraries in iPhone Projects (Part 2)

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!

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!