xcode 详解创建静态库和动态库的方法
xcode 创建静态库和动态库
1、linux中静态库和动态库区别:
库从本质上来说是一种可执行代码的二进制格式
,可以被载入内存中执行。库分静态库和动态库两种。
静态库:这类库的名字一般是libxxx.a;利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了。当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。
动态库:这类库的名字一般是libxxx.so;相对于静态函数库,动态函数库在编译的时候 并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。
2、iOS开发中静态库和动态库区别:
静态库和动态库是相对编译期和运行期的:静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
静态库 好处:
i.模块化,分工合作,提高了代码的复用及核心技术的保密程度
ii.避免少量改动经常导致大量的重复编译连接
iii.也可以重用,注意不是共享使用
动态库 好处:
i.使用动态库,可以将最终可执行文件体积缩小,将整个应用程序分模块,团队合作,进行分工,影响比较小
ii.使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
iii.使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。
iv.应用插件化
v.软件版本实时模块升级
vi.共享可执行文件 在其它大部分平台上,动态库都可以用于不同应用间共享,这就大大节省了内存。从目前来看,iOS仍然不允许进程间共享动态库,即iOS上的动态库只能是私有的,因为我们仍然不能将动态库文件放置在除了自身沙盒以外的其它任何地方。 不过iOS8上开放了App Extension功能,可以为一个应用创建插件,这样主app和插件之间共享动态库还是可行的。
3、xcode创建静态库
打开Xcode, 选择File ----> New ---> Project。 新建工程。 选择iOS ----> Framework & Library ---> Cocoa Touch Static Library。 点击Next。创建工程:
新增2个类作为我们的一个静态类文件:
其中LogLib.h的代码如下:(作为公开存在)
LogLib.m实现方法如下,变成静态库后该文件隐藏:
然后选择真机进行静态库的创建:(command + B)
这个时候会出现如下的错误提示:
按照错误的提示得知我们需要在iOS8.1下build需要选择证书:
好了,在Product
下会存在libStaticLib.a
文件:
这只是真机下的一个静态库,同样选择模拟器,command + B
,生成模拟器下的静态库。
找到这2个新建的静态库文件:
分别用2个.a加入到其他项目在不同运行坏境选择不同的.a静态库明显不明智,打开终端,输入以下命令行进行整合:
lipo
-create
真机.a路径
模拟器.a路径
-output
整合的.a路径
lipo -create /Users/fangdd/Library/Developer/ Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph /Build/Products/Debug-iphoneos/libStaticLib.a /Users/fangdd /Library/Developer/Xcode/DerivedData/StaticLib-ercfdooewtvlxmakqvyxkohcagph /Build/Products/Debug-iphonesimulator/libStaticLib.a -output /Users/fangdd/Desktop/staticLib.a
会在 整合的.a路径
下找到合体的静态库。
将生产的静态库及相应的头文件加入到我们的测试项目中,运行得到:
完毕.
4、xcode创建动态库
打开Xcode, 选择File ----> New ---> Project。 新建工程。 选择iOS ----> Framework & Library ---> Cocoa Touch Framework。 点击Next。创建工程:
命名为DymicLib
:
同样的添加新的2个类作为测试:
将头文件作为公共的头文件,提供给外部调用:
运行后变生成了一个动态库,找到Product
下的DymicLib.framework
所在的目录:
注意这个只是运行坏境下的动态库(模拟器和真机),下面建立新的TARGETS
:命名为CommonDymicLib
:
将之前生成的DymicLib
加入到新的CommonDymicLib
中:
为CommonDymicLib
添加新的脚本来实现模拟器和真机合并:
脚本如下:
# Sets the target folders and the final framework product. FMK_NAME=${PROJECT_NAME} # Install dir will be the final output to the framework. # The following line create it in the root folder of the current project. INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework # Working dir will be deleted after the framework creation. WRK_DIR=build DEVICE_DIR=${WRK_DIR}/Release-iphoneos/$ {FMK_NAME}.framework SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework # -configuration ${CONFIGURATION} # Clean and Building both architectures. # 分别编译生成真机和模拟器使用的framework xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build # Cleaning the oldest. if [ -d "${INSTALL_DIR}" ] then rm -rf "${INSTALL_DIR}" fi mkdir -p "${INSTALL_DIR}" cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/" # Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product. # 使用lipo命令将其合并成一个通用framework # 最后将生成的通用framework放置在工程根目录下新建的Products目录下 lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}" rm -r "${WRK_DIR}"
选择iOS Device
运行:
找到生成的CommonDymicLib
下的动态库DymicLib.framework
:
在测试项目中将DymicLib.framework
加入:
运行即可!
心得:这个时候所谓的动态库其实意义就是升级版的静态库,因为动态库使用的前提是项目在发布前添加到项目中,这和我们所谓的插件
(即插即用,随时在自己的服务器上下载一个动态库运行,而不需要重新打包,我们可以选择在需要的时候再加载动态库)完全是两码事。
插件
实现方式:使用dlopen
加载动态库,动态库中真正的可执行代码为DymicLib.framework/DymicLib
文件,因此使用dlopen
时如果仅仅指定加载动态库的路径为DymicLib.framework
是没法成功加载的。将我们创建的动态库放在我们的服务器,项目上线后再下载这个动态库到我们的Documents
文件夹中,使用如下代码动态使用动态库:
#import <dlfcn.h> NSString *documentsPath = [NSString stringWithFormat:@"%@/Documents/DymicLib.framework/DymicLib",NSHomeDirectory()]; voidvoid * libHandle = NULL; libHandle = dlopen([documentsPath cStringUsingEncoding:NSUTF8StringEncoding], RTLD_NOW); if (libHandle == NULL) { charchar *error = dlerror(); NSLog(@"dlopen error: %s", error); } else { NSLog(@"dlopen load framework success."); }
使用 动态库 中的类:
Class rootClass = NSClassFromString(@"DymicLog"); if (rootClass) { id object = [[rootClass alloc] init]; [(DymicLog *)object relog:@"hello world"]; }
感谢阅读,希望能帮助到大家,谢谢大家对本站的支持!
【文章原创作者:阿里云代理商 http://www.56aliyun.com 欢迎留下您的宝贵建议】