静态库中的 Objective-C 类别 [英] Objective-C categories in static library

查看:32
本文介绍了静态库中的 Objective-C 类别的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

你能指导我如何正确地将静态库链接到 iPhone 项目吗?我使用添加到应用程序项目的静态库项目作为直接依赖项(目标 -> 常规 -> 直接依赖项)并且一切正常,但类别.静态库中定义的类别在应用程序中不起作用.

Can you guide me how to properly link static library to iPhone project. I use static library project added to app project as direct dependency (target -> general -> direct dependencies) and all works OK, but categories. A category defined in static library is not working in app.

所以我的问题是如何将具有某些类别的静态库添加到其他项目中?

So my question is how to add static library with some categories into other project?

一般来说,在其他项目的应用项目代码中使用的最佳实践是什么?

And in general, what is best practice to use in app project code from other projects?

推荐答案

解决方案: 从 Xcode 4.2 开始,您只需转到链接库的应用程序(而不是库本身) 并在项目导航器中单击项目,单击应用程序的目标,然后构建设置,然后搜索其他链接器标志",单击 + 按钮,并添加-ObjC".不再需要-all_load"和-force_load".

Solution: As of Xcode 4.2, you only need to go to the application that is linking against the library (not the library itself) and click the project in the Project Navigator, click your app's target, then build settings, then search for "Other Linker Flags", click the + button, and add '-ObjC'. '-all_load' and '-force_load' are no longer needed.

详情:我在各种论坛、博客和苹果文档上找到了一些答案.现在我试着对我的搜索和实验做一个简短的总结.

Details: I found some answers on various forums, blogs and apple docs. Now I try make short summary of my searches and experiments.

问题是由(引自苹果技术问答 QA1490 https://developer.apple.com/library/content/qa/qa1490/_index.html):

Problem was caused by (citation from apple Technical Q&A QA1490 https://developer.apple.com/library/content/qa/qa1490/_index.html):

Objective-C 没有定义链接器每个函数(或方法,在 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.

以及他们的解决方案:

为了解决这个问题,静态库应该通过 -ObjC 选项到链接器.该标志导致链接器加载每个目标文件定义一个的库Objective-C 类或类别.尽管此选项通常会导致更大的可执行文件(由于额外的目标代码加载到应用程序),它将允许成功创建有效Objective-C 静态库包含现有类别类.

To resolve this issue, the static library should 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.

在 iPhone 开发常见问题中也有推荐:

and there is also recommendation in iPhone Development FAQ:

我如何链接所有的Objective-C静态库中的类?设置其他链接器标志构建设置为-ObjC.

How do I link all the Objective-C classes in a static library? Set the Other Linker Flags build setting to -ObjC.

和标志说明:

-all_load 加载静态存档库的所有成员.

-all_load Loads all members of static archive libraries.

-ObjC 加载静态归档库的所有成员,这些成员实现了一个Objective-C 类或类别.

-ObjC Loads all members of static archive libraries that implement an Objective-C class or category.

-force_load (path_to_archive) 加载指定静态的所有成员档案库.注意:-all_load强制所有档案的所有成员被加载.此选项允许您以特定档案为目标.

-force_load (path_to_archive) Loads all members of the specified static archive library. Note: -all_load forces all members of all archives to be loaded. This option allows you to target a specific archive.

*我们可以使用 force_load 来减少应用二进制文件的大小并避免 all_load 在某些情况下可能导致的冲突.

*we can use force_load to reduce app binary size and to avoid conflicts which all_load can cause in some cases.

是的,它适用于添加到项目中的 *.a 文件.但是我在将 lib 项目添加为直接依赖项时遇到了麻烦.但后来我发现是我的错——直接依赖项目可能没有正确添加.当我删除它并通过步骤再次添加时:

Yes, it works with *.a files added to the project. Yet I had troubles with lib project added as direct dependency. But later I found that it was my fault - direct dependency project possibly was not added properly. When I remove it and add again with steps:

  1. 在应用项目中拖放 lib 项目文件(或使用 Project->Add to project... 添加它).
  2. 单击 lib 项目图标上的箭头 - 显示的 mylib.a 文件名,将此 mylib.a 文件拖放到 Target ->将二进制链接到库组.
  3. 在第一个页面(General)中打开目标信息并将我的库添加到依赖项列表

之后一切正常.-ObjC"就我而言,flag 就足够了.

after that all works OK. "-ObjC" flag was enough in my case.

我也对来自 http://iphonedevelopmentexperiences 的想法感兴趣.blogspot.com/2010/03/categories-in-static-library.html 博客.作者说他可以使用 lib 中的类别而无需设置 -all_load 或 -ObjC 标志.他只是将空的虚拟类接口/实现添加到类别 h/m 文件中,以强制链接器使用此文件.是的,这个技巧很有效.

I also was interested with idea from http://iphonedevelopmentexperiences.blogspot.com/2010/03/categories-in-static-library.html blog. Author say he can use category from lib without setting -all_load or -ObjC flag. He just add to category h/m files empty dummy class interface/implementation to force linker use this file. And yes, this trick do the job.

但作者也说他甚至没有实例化虚拟对象.嗯……正如我发现的,我们应该明确地称一些真实的"类别文件中的代码.所以至少应该调用类函数.我们甚至不需要虚拟类.单个 c 函数做同样的事情.

But author also said he even not instantiated dummy object. Mm… As I've found we should explicitly call some "real" code from category file. So at least class function should be called. And we even need not dummy class. Single c function do the same.

所以如果我们把lib文件写成:

So if we write lib files as:

// mylib.h
void useMyLib();

@interface NSObject (Logger)
-(void)logSelf;
@end


// mylib.m
void useMyLib(){
    NSLog(@"do nothing, just for make mylib linked");
}


@implementation NSObject (Logger)
-(void)logSelf{
    NSLog(@"self is:%@", [self description]);
}
@end

如果我们调用 useMyLib();App项目中的任何地方那么在任何类中我们都可以使用 logSelf 类别方法;

and if we call useMyLib(); anywhere in App project then in any class we can use logSelf category method;

[self logSelf];

以及更多主题博客:

http://t-machine.org/index.php/2009/10/13/how-to-make-an-iphone-static-library-part-1/

http://blog.costan.us/2009/12/fat-iphone-static-libraries-device-and.html

这篇关于静态库中的 Objective-C 类别的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆