From: http://blog.coderow.com/2012/08/23/building-an-ios-universal-static-library/
If you have only built applications in iOS, let this be a gentle introduction to creating static libraries for iOS applications. The reasons for doing this are multiple. You may have a set of applications that need to share code with a very well defined interface. You may want to distribute a library to your customers to allow them to build in some of your technology into their application. You may want to use some Objective-C code into your RubyMotion project. In any case, here is a simple example to take you from an app where the code is all together, to one that uses a library for some of the code.
The Starting App
The app that I am using to demonstrate a static library is very simple. There is a class for the view controller and a “computation” class that will be in the library. There is also an application delegate class to get this started.
To create this app, go to XCode and create an empty sample application called TheQuestion.
From there, right click on the yellow TheQuestion folder and select New File…. Create an Objective-C class from the iOS | Cocoa Touch menu. Have UIViewController be the superclass and have the class name be QuestionViewController. Do New File again and this time create a class called TheAnswer with a superclass of NSObject.
You can then copy and paste the following code snippets in.
AppDelegate.m
AppDelegate.m - in import section
1
|
|
AppDelegate.m - before [self.window makeKeyAndVisible]
1 2 3 |
|
QuestionViewController.h
QuestionViewController.h
1 2 3 4 5 6 7 8 |
|
QuestionViewController.m
QuestionViewController.m
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
|
TheAnswer.h
TheAnswer.h
1 2 3 4 5 6 7 |
|
TheAnswer.m
TheAnswer.m
1 2 3 4 5 6 7 8 9 10 |
|
The result should then be:
Creating the Static Library
Now that we have a working app, we want to split the TheAnswer class into its own library so we can share its goodness with others. The first step is to create a new project that is a Cocoa Touch Static library. Select New | Project… from the XCode menu and then select Cocoa Touch Static Library and call it the TheAnswerLibrary for the project name.
After creating the library, you should delete the two generated files called TheAnswerLibrary.h and TheAnswerLibrary.m.
Then add in TheAnswer.h and TheAnswer.m by:
- control-clicking on the yellow TheAnswerLibrary folder
- selecting Add files to “TheAnswerLibrary”…
- browsing over to the TheQuestion project
- select both TheAnswer.h and TheAnswer.m
You library is now complete. Do a build and it should build successfully.
Creating the App that uses the new library
The next step is to create a new project that will use the library. Create an empty project like you did in the first step and call it TheQuestionApp. Replace the AppDelegate.m with the AppDelegate.m from the TheQuestion project. Add the QuestionViewController .h and .m files to the TheQuestionApp folder like we did for the TheAnswer .h and .m files for the static library.
If you try to build it at this point, you will get a TheAnswer.h not found error. You can add TheAnswer.h from the TheQuestion project and it will then compile but will fail to link.
Getting the library file
If you go back to the TheAnswerLibrary project and display the Products, you will see the built library: libTheAnswerLibrary.a.
You want to add this file to the TheQuestionApp project. To add it, control-click on the libTheAnswerLibrary.a and select Show In Finder. You can then just drag this into the TheQuestionApp project files. Alternatively, you could copy the file and paste it into the TheQuestionApp’s folder and then add it using the Add Files option. The former method is nice because it just references the built library so that when you rebuild the library the changes are reflected the next time you do a build in the TheQuestionApp.
Now that have it in the TheQuestionApp, try to run it in the simulator. You should get the following error:
This happens because the library that you built only contains symbols for ARM. The simulator builds are i386 builds. If you go back to the TheAnswerLibrary project and selected the scheme TheAnswerLibrary > iPhone 5.1 Simulator and did a build, then it would build an i386 build. I tried to use that library to run in the simulator but got a strange error which said:
ld: warning: ignoring file /Users/username/Projects/Blogging/combined_library/TheQuestionApp/TheQuestionApp/libTheAnswerLibrary.a, file was built for archive which is not the architecture being linked (i386): /Users/username/Projects/Blogging/combined_library/TheQuestionApp/TheQuestionApp/libTheAnswerLibrary.a
In order to get it to run on the simulator and on device, you need to combine those libraries into one that contains all the symbols and architectures that you need.
Generating a combined library
Go back to the TheAnswerLibrary project and select the blue project icon. We want to add a new target. On the bottom of the project settings, you can add a new target:
You want to add an Aggregate Target:
Once the target is added, then you will add a custom script to run for that target. There is a button on the lower right of the project settings:
After clicking on that, you want to add a run script.
In the script editor section paste in the following script:
TheAnswer.m
1 2 3 4 5 6 7 |
|
This builds both versions of the library and then combines them into one that has all the architectures you need. To try this out and see if it is working first before putting it into XCode, create a build.sh file in the root of your project and run it.
If you select the scheme Combined and then do a build, you will find in your projects folder a build folder that contains the combined library.
Adding ARM6 support
If you want your library to run on older iPhones, then you need to add in ARM6 support. To enable this, you want to go to the Build Settings and change the Architectures to include armv6, armv7 and i386. Here is the Architecture line of the build settings:
When you select the column underneath blue TheAnswerLibrary you should see
remove the only entry and add in armv6, armv7 and i386.
Now if you build the combined target, your library will have all the architectures you need.