Getting OCMock to work with an iPhone Project

The OCMock static library contains only "categories" and not "classes"


From the OCMock Site itself:

OCMock static libraryThe OCMock Xcode project contains additional targets that build a static library of OCMock. When a test project links against this library (and not the framework) the OCMock classes are included in the binary itself, which means they can be run on an iOS device. The default library is built "fat", containing binary code for i386, which is required for the simulator, and armv7, which is required for running on the device. Thus, if a project requires both logic and application tests, it can do this by using the same library; the framework is not needed for either of them.
To use the library in an iOS project, you have to make the actual library, ie. libOCMock.a, as well as the header files available to the project containing the tests. One way of achieving this is to copy the library and headers into a directory named "Libraries" in the project directory (this does not exist by default) and then adding the following flags to the project:
LIBRARY_SEARCH_PATHS = $(inherited) "$(PROJECT_DIR)/Libraries"

Due to some issues, which are described in this Apple Technical Q&A, you also have to add the following flags:
OTHER_LDFLAGS = -ObjC -force_load $(PROJECT_DIR)/Libraries/libOCMock.a
If you have copied the library or headers to a different place all of these settings must be adjusted accordingly.

Technical Q&A QA1490
Building Objective-C static libraries with categories

Q: Why do I get a runtime exception of "selector not recognized" when linking against an Objective-C static library that contains categories?
A: The "selector not recognized" runtime exception occurs due to an issue between the implementation of standard UNIX static libraries, the linker and the dynamic nature of Objective-C. Objective-C does not define linker symbols for each function (or method, in Objective-C) - instead, linker symbols are only generated for each class. If you extend a pre-existing class with categories, the linker does not know to associate the object code of the core class implementation and the category implementation. This prevents objects created in the resulting application from responding to a selector that is defined in the category.

To resolve this issue, the target linking against the static library must pass the -ObjC option to the linker. This flag causes the linker to load every object file in the library that defines an Objective-C class or category. While this option will typically result in a larger executable (due to additional object code loaded into the application), it will allow the successful creation of effective Objective-C static libraries that contain categories on existing classes. Follow these steps to pass -ObjC to the linker:

1. In Xcode, double-click the target's name under "Targets" in the Project window.

2. Choose the Build pane from the ensuing Info window.

3. Scroll down to the Other Linker Flags build setting under the Linking collection and set its value to -ObjC.

Figure 1: Target Build pane: Other Linker Flags


IMPORTANT: For 64-bit and iPhone OS applications, there is a linker bug that prevents -ObjC from loading objects files from static libraries that contain only categories and no classes. The workaround is to use the -all_load or -force_load flags.

-all_load forces the linker to load all object files from every archive it sees, even those without Objective-C code. -force_load is available in Xcode 3.2 and later. It allows finer grain control of archive loading. Each -force_load option must be followed by a path to an archive, and every object file in that archive will be loaded.

Document Revision History
2010-04-30 Describes how to pass the "-ObjC" option to the linker. Updated for Mac OS X v10.6 and later.
2006-10-03 Changed "and" to "an" in order to make the content correct.
2006-09-25 New document that describes how to properly build Objective-C static libraries that contain categories on existing classes.

Unless otherwise stated, the content of this page is licensed under Creative Commons Attribution-ShareAlike 3.0 License