How can I build an Objective-C static library to d

2020-06-20 09:29发布

I'm building a static library, MyLibrary, for iOS in Objective-C that bundles together a dozen useful classes, each with its own .h file. I'd like to distribute MyLibrary as a single compiled binary, libMyLibrary.a, and a single .h header file, MyLibraryAPI.h. MyLibraryAPI.h has a dozen #import statements, one for each of MyLibrary's dozen public classes. Developers who want to include MyLibrary in their host projects should only have to include the libMyLibrary.a binary and the MyLibraryAPI.h header. This is the goal.

So I have set the Role of each public class in the MyLibrary Xcode project to Public and built libMyLibrary.a successfully using Xcode command line build utils and lipo. Then, I manually included all of the dozen MyLibrary header files along with libMyLibrary.a in a host project, and the host project can use the public MyLibrary classes with no problem. Awesome!

The problem is if I remove those dozen header files and use MyLibraryAPI.h instead (as is my goal), the host project's classes can no longer find the MyLibrary header files referenced in MyLibraryAPI.h. Instead, at compile time, I get errors like: MyAwesomeThingDelegate.h: No such file or directory... for each MyLibrary class that I try to #import in MyLibraryAPI.h. I have a folder in my host project root directory called lib and in host project build settings have set the recursive header search path to lib/** and in Library Search Path, set a recursive path to lib/**.

I'd love to hear suggestions from the community on how to correctly set the host project's search paths so that I only need to include libMyLibrary.a and MyLibraryAPI.h to use the MyLibrary classes. Or if I'm doing something wrong, I'd love to hear another suggestion to achieve my goal of distributing a single binary and a single API header file.

2条回答
疯言疯语
2楼-- · 2020-06-20 10:07

I've had the same challenge and I've come with the following solution:

First, I tried to hide as many implementation details as possible. For that reason, I usually built pairs of classes: one class is the public interface and the other one the private implementation. The public class has only one member instance: the pointer to the implementation. The private class has just a forward declaration.

@class MyViewImpl;

@interface MyView : UIView
{
    @private
    MyViewImpl* _internal;
}

@property (nonatomic, assign) CGRect highlightArea;
- (void) startAnimation;

@end

Second, I put all the public declarations into a single header file. It's as comfortable to work with as with separate header file, but it works. The only imports that are left, are import of iOS stuff, such as:

#import <UIKit/UIKit.h>
查看更多
劫难
3楼-- · 2020-06-20 10:24

I'm giving a second answer here with a different approach.

The way Objective C works is, that the compiler needs the full declaration (i.e. the header files) of all the classes that the users of your library will directly call. The library file (the .a file) only contains the compiled code and no declaration. It will only be used by the linker, which is one of the last steps of building an application.

[Programming languages like C or C++ are the same. Programming languages like Java or C# however store meta information about classes in the compiled code so they don't need no header files, just the .jar or .dll file.]

So one approach would be to give the .a and a directory full of header files to your user. They then add the .a file to their project, add a single #import statement wherever they use your classes and add the path to the header file directory to their build settings (it's called Header Search Paths).

查看更多
登录 后发表回答