Finding an elegant way to reuse and share code (i.e., libraries) across
separate iPhone applications can be a bit tricky at first, especially
considering Apple’s restrictions on dynamic library linking and custom
Frameworks. Most people agree that the best solution is to use
static libraries. This tutorial builds on that solution, showing how your Xcode project can
reference a second Xcode project–one
which is used to build a static library. This allows you to
automatically build that static library with the rest of your app, using
your current build configuration (e.g., debug, release, etc.) and avoid
pre-building several versions of the library separately (where each
version was built for a specific environment/configuration).
Problem: What’s the best way to share code across iPhone projects?
If you want to reuse/share code across different iPhone applications, you only have two options (that I’m aware of):
- Copy all of the source code from the “shared” library into your own project
- Keep the shared library code in a separate Xcode project and use it
to build static libraries (e.g., libSomeLibrary.a, also referred to as
“archive files”) that can be referenced by your project and used via
static linking.
The first option, copying the files, should be avoided when possible
since it’s inherently redundant and contrary to the goal of keeping
“common code” modular and atomic. It’s a much better idea to put the
code in a static library since, as mentioned
in the introduction, dynamic linking to custom libraries/frameworks
isn’t allowed by Apple when it comes to iPhone apps. If you’re not sure
how to put your code in a static library, I’d suggest taking a look at this tutorial on the Stormy Productions blog.
当拷贝文件本身就是冗余的,且和保持“通用代码“模块化和原子化的目标相悖,第一种方案就应该避免采用。
So we’ve established that the second option is preferable, but
there’s a catch: you’ll need to build and distribute multiple versions
of the static library–one for each runtime environment and build
configuration. For example, you would need to build both “release” and
“debug” versions of the library for the Simulator, as well as other
pairs for the iPhone or iPod device itself. How can we avoid manually
pre-building and managing separate .a files?
Solution: Static libraries that are built on-demand via Xcode cross-project references
The trick to avoid pre-building static libraries for each environment
is to use an Xcode “cross-project reference” so that those libraries
are built dynamically (i.e., when you build your own app) using your
app’s current build configuration. This allows you to both reuse shared
source code and avoid the headache of managing multiple versions of the library. Here’s how it works at a high level:
在build app的时候动态生成静态库。
- The shared code lives in its own Xcode project that, when built, results in one or more static libraries.
- You create an Xcode environment variable with a path to the directory that contains the static library’s *.xcodeproj file.
- All iPhone apps that need the static library will use the aforementioned environment variable to reference the library’s Xcode project, including any static library in that project and the related header files.
- Each time you build your project for a specific
configuration/runtime environment, the shared project library will also
be built for that config/environment–if it hasn’t already–and linked
with your executable.
In addition to solving the main problem (reusing code and avoiding
management of multiple library versions), there are a couple of nice
benefits to this strategy. First, if you make changes to the shared
library source code, those changes will immediately be included the next
time you build your own project (via the cross-project reference).
Second, you can modify the Xcode environment variable to point to
different versions of any project. For example, you might have separate
directories for “somelibrary-1.0″ and “somelibrary-2.0″; as you’ll see
in the detailed solution instructions, it’s easy to modify the
environment variable and switch your project to a different version of
“somelibrary.”
Other Solutions
zerg-xcode
Victor Costan has developed a slick command-line tool called “zerg-xcode”
which helps you copy the source code from one Xcode project (i.e., a
static library project) into another Xcode project. In addition to
physically copying the files, it inserts the targets from the “library”
project into your “app” project. If the library project changes, you
simply run zerg-xcode again with the approriate commands to sync the
files and targets. Some people may find this tool very useful; my
personal preference, however, is to avoid making any copies of the
source code files and stick to Xcode’s built-in “cross-project
reference” mechanism.
“Fat” Universal Binary
Another approach is to “bundle” two versions of a static library into
a single file, referred to as a “fat” universal binary (see this post
on the Latenitesoft blog for an example). More specifically, one
version of the library would be for the i386 architecture (i.e., the
Simulator) and the second for the ARM architecture (i.e., the phone).
This may be a perfectly fine solution for you if you really only need
two versions, or if the source code for the library is kept private.
That said, you’re still left with the task of maintaining pre-built
versions of the libraries (plus the extra work of bundling them into the
single file). In addition, I’m not sure that you can bundle more than
two versions of the library into the binary (e.g., iPhone “release” and
Simulator “release”, but not iPhone “debug” and Simulator “debug”).
posted on 2013-08-16 11:39
Long 阅读(191)
评论(0) 编辑 收藏 引用 所属分类:
iOS