• (iOS)谈谈关于使用category的静态库(原创)


      最近在一个项目中使用了一个包含catecategory 的静态库,但是此项目在运行过程中,该静态库调用 category 增加的方法处,却报 selector not recognized 异常,会直接crash。

      我的开发环境是xcode5.0。

      在网上查了一下原因和解决的办法,在此做个总结。

         产生这个问题的原因,苹果官方提供的文档,Q&A QA1490:Building Objective-C static libraries with categories 

      在连接一个含有category的静态库的时候,往往会得到一个运行时exception “selector not recognized”。这是由于 UNIX的静态库实现、linker和Objective-C的动态结构三者之间的问题引起的。

    Objective-C并不为每个函数定义linker symbol,它只为每个class生成linker symbol。(objc的动态结构)如果你为一个已存在的class创建了category,那么linker并不知道要将原始class实现和category实现联系起来。这就导致了最终程序中的对象没法响应category中的方法。

      

    为了解决这个问题,目前我知道以下几个方法:

    1.将category文件跟静态库一起导入到工程。

      这让很多想保持工程独立性,并且有代码洁癖的人感觉很不舒服,包括我,随着这个是非常直接并且简单的方法,但是不能保持静态库的独立性,而且多个地方存在同一份文件,可能会带来另外一些问题。

    2.在使用静态库的 target 要将 -ObjC 选项传递给 linker,这个标志将会使得 linker 将静态库中原始类及 category 的类文件都载入!

      设置 -ObjC 选项对于 iOS 程序来说有时是不够的,这是因为 linker 中存在一个 bug,所以还是可能会在 -ObjC 的情况下导致 selector not recognized 的异常,为了避免这个 bug,在 Other Linker Flags 中,我们将其值设置为 -all_load 或者 -force_load 即可。

    -all_load 与 -force_load 说明

    • -all_load :linker 会将所有可见的文件都载入到静态库中
    • -force_load :从 Xcode3.2之后才有的选项,能使得文件的载入更细化,每一个你要载入的文件,都要增加一个 -force_load 选项,并且在 -force_load 后面跟上要导入的文件路径。例如:
      -force_load $(BUILT_PRODUCTS_DIR)/<library_name.a>  

    使用 -all_load 会导致很多多余文件的导入,会导致静态库体积变大;

    使用 -force_load 会很麻烦,要一个个手动添加,但是针对性强。我选择的是这个。

    3.在你的category的实现文件开头写一个空的class,来避免在 iOS 中使用 -ObjC 的 linker 的 bug。但是记住,还是需要把使用静态库的 Target 中的 Building Setting 的 Other Linker Flags 设置成 -ObjC 。

      关于方案的选择,这要因人而异了。

  • 相关阅读:
    完全卸载Android Studio(卸载得干干净净)
    每日生活总结1
    求解协方差矩阵
    每天一个linux命令:ifconfig命令 临时修改重启后恢复原样
    每天一个linux命令(58):telnet命令
    每天一个linux命令:pwd命令
    每天一个linux命令(38):cal 命令
    每天一个linux命令:scp命令
    login shell与non-login shell的区别
    linux下重要的网络配置文件
  • 原文地址:https://www.cnblogs.com/hikoming/p/3485822.html
Copyright © 2020-2023  润新知