库本质上讲是一种可执行的二进制格式,可以载入内存中执行。是程序代码的集合,共享代码的一种方式。
静态库是闭源库,不公开源代码,都是编译后的二进制文件,不暴露具体实现。
静态库 一般都是以 .a 或者 .framework 形式存在。
静态库编译的文件比较大,因为整个函数库的数据都会被整合到代码中,这样的好处就是编译后的程序不需要外部的函数库支持,不好的一点就是如果改变静态函数库,就需要程序重新编译。多次使用就有多份冗余拷贝。
使用静态库的好处:模块化分工合作、可重用、避免少量改动导致大量的重复编译链接。
一般公司都会有核心开发团队和普通开发团队,然后公司的核心业务由核心开发团队写成静态库然后让普通开发团队调用,这样就算普通开发团队离职也带不走公司的核心业务代码。一般核心开发团队是不会离职的。
有静态库自然就有动态库了。这里所谓的静态和动态是相对编译期和运行期的。
静态库在程序编译时会被链接到代码中,程序运行时将不再需要改静态库,而动态库在编译时不会被链接到代码中,只有程序运行时才会被载入,所以 hook 别人程序或者说做插件都是运用了 runtime 机制,然后动态库注入修改的。
制作 .a 文件时候,要注意 CPU 架构的支持,i386、X86_64、 armv7、armv7s。 查看可以通过命令 “ lipo -info 静态库名称” 。模拟器 .a 文件和真机 .a 文件合并可以通过 "lipo -create 模拟器静态库1名 真机静态库2名 -output 新静态库名称"
一些坑
命名不要太随意,毕竟是被别人拿过去用的要能看懂。
-
framework中用到了NSClassFromString,但是转换出来的class 一直为nil。解决方法:在主工程的【Other Linker Flags】需要添加参数【-ObjC]即可。
-
如果Xcode找不到框架的头文件,你可能是忘记将它们声明为public了。 解决方法:进入target的Build Phases页,展开Copy Headers项,把需要public的头文件从Project或Private部分拖拽到Public部分。
-
尽量不要用 xib 。由于静态框架采用静态链接,linker会剔除所有它认为无用的代码。不幸的是,linker不会检查xib文件,因此如果类是在xib中引用,而没有在O-C代码中引用,linker将从最终的可执行文件中删除类。这是linker的问题,不是框架的问题(当你编译一个静态库时也会发生这个问题)。苹果内置框架不会发生这个问题,因为他们是运行时动态加载的,存在于iOS设备固件中的动态库是不可能被删除的。
有两个解决的办法:
1、 让框架的最终用户关闭linker的优化选项,通过在他们的项目的Other Linker Flags中添加-ObjC和-all_load。
2、 在框架的另一个类中加一个该类的代码引用。例如,假设你有个MyTextField类,被linker剔除了。假设你还有一个MyViewController,它在xib中使用了MyTextField,MyViewController并没有被剔除。你应该这样做:
在MyTextField中:
+(void)forceLinkerLoad_ {}
在MyViewController中:
+(void)initialize {[MyTextField forceLinkerLoad_];}
他们仍然需要添加-ObjC到linker设置,但不需要强制all_load了。
第2种方法需要你多做一点工作,但却让最终用户避免在使用你的框架时关闭linker优化(关闭linker优化会导致object文件膨胀)。
网友评论