Static Libraries woes with categories and iOS

Like most developers, I assume, I have a lot of utility functions and category methods that I rely on from project to project. Importing all those files into each project, while allows customization, does tend to be tedious, error-prone, and a bit amateurish (IMO). So, I created several stand-alone libraries for Core Foundation, Core Data, and UIKit “extensions”. Simple, no big deal. Just don’t forget to add -ObjC via the Other Linker Flags to your Build Settings of the project that is linking to the static libraries. (See Apple’s Technical Q&A QA1490).

Unfortunately, there exists an issue with the linker where this linker flag doesn’t work as advertised in certain environments (iOS and 64-bit Mac applications) when you have only categories defined, but no classes. When you build your application, you not get any errors about unrecognized categories (assuming you have defined and exposed them via #import header correctly).

When you merrily go about running the application and it tries accessing one of these categories defined in a static library, you get an exception thrown that reads a bit like:

2011-06-04 08:34:50.823 <App Name> [24476:207] +[<Class> <method>:]: unrecognized selector sent to class 0x68e00

In this case, I was calling a class method, but instance methods will be affected as well. Also, if it isn’t obvious, the class address will be different from session to session.

So, the solution for now is to replace -ObjC with either -all_load or -force_load.

Using -force_load requires a path to the archive (static library), whereas -all_load is a shot-gun approach for all archives linked into the project. Each forces the linker to pull in all object files from the archive(s). This is not perfect in that it would be nice to take advantage of the linkers ability to strip out unused symbols, among other potential issues (such as forcing loads of other symbols from other, possibly unknown, archives).

As far as I can tell, there is no harm in defining in Other Linker Flags both -ObjC and either -all_load or -force_load, nor do I see an advantage to it. -all_load or -force_load pretty much override -ObjC entirely.

Comments are closed.