概念:静态库/动态库/静态链接库/动态链接库

什么是库:  
               库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行

为什么用库:
   如果你作为iOS开发者已经有一段时间,可能会有一套属于自己的类和工具函数,它们在你的大多数项目中被重用。
重用代码的最简单方法是简单的 拷贝/粘贴 源文件。然而,这种方法很快就会成为维护时的噩梦。因为每个app都有自己的一份代码副本,你很难在修复bug或者升级时保证所有副本的同步。
这就是静态库要拯救你的。 一个静态库是若干个类,函数,定义和资源的包装 ,你可以将其打包并很容易的在项目之间共享。

库的分类:
              函数库分为静态库和动态库两种

不同的库的优缺点:
//静态库是在编译器编译的;
  优点:包含所有需要的函数   
  缺点:文件较大 ; 如果静态库改变,程序必须重新编译

//动态函数库是在运行是编译的;
优点:文件较小;在我那件运行期间才被载入;动态函数库改变不会影响程序 ,升级方便
缺点:苹果不让用(共享库)


为什么使用静态库:
创建静态库可能出于以下几个理由:
1.你想将一些你和你团队中的同事们经常使用的类打包并轻松的分享给周围其他人。
2.你想让一些通用代码处于自己的掌控之下,以便于修复和升级。
3.你想将库共享给其他人,但不想让他们看到你的源代码。
4. iPhone官方只支持静态库联编,不支持动态链接库

静态库的分类:
静态库有两种方式:一种是生成.a文件  一种是生成静态framework( 所谓的静态framework,实际上也是一种静态库,其相对于.a文件来说,区别在于其不仅包含了库文件,还包含了头文件和资源文件。而在使用.a文件时,还要另外添加.h文件。 )
                       
静态库的部分概念:

在 Xcode 提供的构建设置中,有一项称为“MACH_O_TYPE ”,其作用是定义输出的产品文件格式以及产品文件用于其他产品构建时如何被链接。它的取值如下所示:

1、可执行文件(mh_execute)(.app)

2、动态链接库(mh_dylib)(.dylib)

3、包(mh_bundle)(.bundle)

4、静态链接库(staticlib)(.a)

5、可重定位的对象文件(mh_object)(.o)

作为iOS开发者,基本上只要关心可执行文件Bundle静态链接库就可以了。动态链接库没法用,而静态库(archieve)是.o的文件包,所以静态库完全可以替代.o文件。

出于某些目的,比如设计架构上将功能与展现相分离,或者重要功能与边缘功能相分离,或者只是为了模块功能划分的清晰性等等,软件在设计时可能会分成几个工程来做。而对于iOS程序来说,最终提供给移动端用户的产品只能是ipa,即一个可执行程序,而其他工程所能提供的只能为其服务。这时程序员所能选择的只有bundle或者静态库。本文将就静态库的一些使用经验、技巧做出叙述,对于bundle的使用,将在另外的文章里进行叙述。

最后稍微科普一下动态链接库和静态链接库:

静态链接是在编译时进行的,静态链接库(.a文件)实际上就是编译好的程序代码,如果有两个程序都用到了同一个库的话,且同时运行这两个程序,那么内存中会有两份相同的库的代码。动态链接是在运行时进行的,由操作系统管理,如果两程序都用同一个DLL的话,实际上内存中只有一份代码。由于iOS开发严格的权限管理,即基本只限于沙盒内,所以动态链接库这种东西是不准使用的



framework框架的分类:
framework也分为静态框架和动态框架大部分框架都是动态链接库的形式。因为只有苹果才能在iOS设备上安装动态库,所以我们也无法创建动态框架( 苹果也从Xcode中移除了创建静态iOS框架的功能 )

framework框架静态框架:
深入理解framework(框架,其实相当于静态框架,不是动态库)
打包framework还是一个比较重要的功能,可以用来做一下事情:
(1)封装功能模块,比如有比较成熟的功能模块封装成一个包,然后以后自己或其他同事用起来比较方便。
(2)封装项目,有时候会遇到这个情况,就是一家公司找了两个开发公司做两个项目,然后要求他们的项目中的一个嵌套进另一个项目,此时也可以把嵌套的项目打包成framework放进去,这样比较方便。

framework框架静态框架的分类:
                                       伪框架真框架

framework框架选择依据:
·         如果你不想修改Xcode,那么请使用“伪”框架版本
·         如果你只是想共享二进制(不是项目),两种都可以
·         如果你想把框架共享给不想修改Xcode的开发者,使用“伪”框架版本
·         如果你想把框架共享给修改过Xcode的开发者,使用“真”框架版本
·         如果你想把框架项目作为另一个项目的依赖(通过workspace或者子项目的方式),请使用“真”框架(或者“伪”框架,使用-framework——见后)
·         如果你想在你的框架项目中加入其他静态库/框架,并把它们也链接到最终结果以便不需要单独添加到用户项目中,使用“伪”框架










一、动态链接库与静态链接库的区别

  库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行

  函数库分为静态库和动态库两种。和多数动态语言和静态语言一样,这里的所谓静态和动态是相对编译期运行期的:
     静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;而动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。

//静态和动态是相对于编入时期不同;
   
windows 中的区分:

静态链接库和动态链接库

         1.静态链接库(.LIB):函数和数据被编译进一个二进制文件。发布时,只需要发布这个可执行文件,并不需要发布被使用的静态库。

         2.动态库(.DLL):在使用动态库的时候,往往提供两个文件:一个引入库(.lib)文件和一个DLL(.dll)。虽然引入库和静态库的后缀名相同,但是差别很大。对于一个DLL来说,其引入库文件包含该DLL导出的函数和变量的符号名,而.dll文件包含DLL的实际的函数和数据。在使用动态链接库的情况下,在编译链接可执行文件时,只需要DLL的引入库文件,而在运行可执行程序时,需要加载所需要的DLL,发布产品时,需要发布调用的动态链接库。



1. 静态函数库  libxxx.a ----- 静态库有两种方式:一种是生成.a文件  一种是生成静态framework( 所谓的静态framework,实际上也是一种静态库,其相对于.a文件来说,区别在于其不仅包含了库文件,还包含了头文件和资源文件。而在使用.a文件时,还要另外添加.h文件。 )
 这类库的名字一般是libxxx.a
利用静态函数库编译成的文件比较大,因为整个函数库的所有数据都会被整合进目标代码中,他的优点就显而易见了,即编译后的执行程序不需要外部的函数库支持,因为所有使用的函数都已经被编译进去了
静态库在程序编译时会被链接到目标代码中,程序运行时将不再需要改静态库;
当然这也会成为他的缺点,因为如果静态函数库改变了,那么你的程序必须重新编译。

2. 动态函数库  libxxx.so
    这类库的名字一般是libxxx.so;
相对于静态函数库,动态函数库在编译的时候并没有被编译进目标代码中,你的程序执行到相关函数时才调用该函数库里的相应函数,因此动态函数库所产生的可执行文件比较小。
   动态库在程序编译时并不会被链接到目标代码中,只是在程序运行时才被载入,因为在程序运行期间还需要动态库的存在。
   由于函数库没有被整合进你的程序,而是程序运行时动态的申请并调用,所以程序的运行环境中必须提供相应的库。
   动态函数库的改变并不影响你的程序,所以动态函数库的升级比较方便。

//静态库是在编译器编译的;
  优点:包含所有需要的函数   
  缺点:文件较大 ; 如果静态库改变,程序必须重新编译


//动态函数库是在运行是编译的;
优点:文件较小;在我那件运行期间才被载入;动态函数库改变不会影响程序 ,升级方便
缺点:苹果不让用(共享库)

二、使用库的优势

在实际的编程过程中,通常会把一些公用函数制成函数库,供其它程序使用,一则提高了代码的复用;二则提高了核心技术的保密程度。

使用静态库好处

1,模块化,分工合作

2,避免少量改动导致大量的重复编译连接

  3,也可以重用,注意不是共享使用


   动态库使用有如下好处:
1,使用动态库,可以将最终可执行文件体积缩小
2,使用动态库,多个应用程序共享内存中得同一份库文件,节省资源
3,使用动态库,可以不重新编译连接可执行程序的前提下,更新动态库文件达到更新应用程序的目的。


三、iPhone对于链接库的支持

iPhone官方只支持静态库联编,不支持动态链接库

而对于静态库有两种方式:一种是生成.a文件
                                           一种是生成静态framework。所谓的静态framework,实际上也是一种静态库,其相对于.a文件来说,区别在于其不仅包含了库文件,还包含了头文件和资源文件。而在使用.a文件时,还要另外添加.h文件。


概括起来,一个静态库工程和一个应用工程非常相似。可以拥有一个或多个类,最后的产品是头文件和一个.a文件。这个.a文件就是可以链接到多个应用程序中的静态库

iPhone不支持动态链接库的原因可能有:

共享给谁?(因为在现在的iPhone,iPodTouch,iPad上面程序都是单进程的,也就是某一时刻只有一个进程在运行,你使用的时候只有你一个应用程序存在,其他的应该被挂起了,即便是可以同时多个进程运行,别人能使用你的共享库里的东西吗?你这个是给你自己的程序定制的。)


目前苹果的AppStore不支持模块更新,无法更新某个单独文件(除非自己写一个更新机制:有自己的服务端放置最新动态库文件),也就是说,就算你通过其他方式产生了动态链接库,也无法达到更新动态库文件从而更新应用程序的目的。

四、Xcode对于创建库的支持


Xcode不支持自己创建动态链接库

framework也分为静态框架和动态框架大部分框架都是动态链接库的形式。因为只有苹果才能在iOS设备上安装动态库,所以我们也无法创建动态框架

而且苹果也从Xcode中移除了创建静态iOS框架的功能!!!

通常来说,Xcode只支持创建静态库文件.a。但是实际上Appstore是允许代码封装在静态链接库中的。所以,出现了所谓的伪框架真框架


///1.iPhone官方只支持静态库联编,不支持动态链接库
         2.而对于静态库有两种方式:一种是生成.a文件
                                                       一种是生成静态framework  (区别: 所谓的静态framework,实际上也是一种静态库,                 其相对于.a文件来说,区别在于其不仅包含了库文件,还包含了头文件和资源文件 )
         3.Xcode不支持自己创建动态链接库
         4.framework也分为静态框架和动态框架大部分框架都是动态链接库的形式(苹果自己的 framework )
         5.苹果也从Xcode中移除了创建静态iOS框架的功能
         6.通常来说,Xcode只支持创建静态库文件.a
         7.但是实际上Appstore是允许代码封装在静态链接库中的。所以,出现了所谓的伪框架真框架

静态库的替代 — framework(即 框架)

深入理解framework(框架,其实相当于静态框架,不是动态库)

打包framework还是一个比较重要的功能,可以用来做一下事情:

(1)封装功能模块,比如有比较成熟的功能模块封装成一个包,然后以后自己或其他同事用起来比较方便。

(2)封装项目,有时候会遇到这个情况,就是一家公司找了两个开发公司做两个项目,然后要求他们的项目中的一个嵌套进另一个项目,此时也可以把嵌套的项目打包成framework放进去,这样比较方便。



我们为什么需要框架(Framework)? 静态framework,实际上也是一种静态库,其相对于.a文件来说,区别在于其不仅包含了库文件,还包含了头文件和资源文件

要想用一种开发者友好的方式共享库是很麻烦的。你不仅仅需要包含库本身,还要加入所有的头文件,资源等等。


苹果解决这个问题的方式是框架(framework)。基本上,这是含有固定结构并包含了引用该库时所必需的所有东西的文件夹。不幸的是,iOS禁止所有的动态库。同时,苹果也从Xcode中移除了创建静态iOS框架的功能。

Xcode仍然可以支持创建框架的功能,重启这个功能,我们需要对Xcode做一些小小的改动。

把代码封装在静态框架是被app store所允许的。尽管形式不同,本质上它仍然是一种静态库。


框架(Framework)的类别

大部分框架都是动态链接库的形式。因为只有苹果才能在iOS设备上安装动态库,所以我们无法创建这种类型的框架。

静态链接库和动态库一样,只不过它是在编译时链接二进制代码,因此使用静态库不会有动态库(运行时载入)那样的问题(即除了苹果谁也不能在iOS上使用动态库)。


五、框架的类别和使用

前面说了, framework 框架分为静态框架和动态框架,对于静态框架,在生成过程中又有了的区别。

1框架
框架是破解的“reloacatable object file”(可重定位格式的目标文件, 保存着代码和数据,适合于和其他的目标文件连接到一起,用来创建一个可执行目标文件或者是一个可共享目标文件),它可以让Xcode编译出类似框架的东西——其本质是一个bundle(包)

伪框架模板把整个过程分为几个步骤,用某些脚本去产生一个真正的静态框架(基于静态库而不是reloacatable object file)。而且,框架项目还是把它定义为wrapper.cfbundle类型,一种Xcode中的二等公民


因此它跟静态框架一样可以正常工作,但当存在依赖关系时就有麻烦了。


依赖问题
如果不使用依赖,只是创建普通的项目是没有任何问题的。但是如果使用了项目依赖(比如在workspace中),Xcode就悲剧了。当你点击“Link Binary With Libraries”下方的’+’按钮时,伪框架无法显示在列表中。你可以从你的框架项目的Products下面将它手动拖入,但当你编辑你的主项目时,会出现警告:

warning: skipping file '/somewhere/MyFramework.framework' (unexpectedfile type 'wrapper.cfbundle' in Frameworks & Libraries build phase)

并伴随框架中的链接错误。

幸运的是,有个办法来解决它。你可以在”Other Linker Flags”中用”-framwork”开关手动告诉linker去使用你的框架进行链接:

-framework MyFramework

警告仍然存在,但起码能正确链接了


2框架
框架各个方面都符合的标准。它是真正的静态框架,正如使用苹果在从Xcode中去除的那个功能所创建的一样。
为了能创建真正的静态框架项目,你必需在Xcode中安装一个xcspec文件。
如果你发布一个框架项目(而不是编译),希望去编译这个框架的人必需也安装xcspec文件(使用本次发布的安装脚本),以便Xcode能理解目标类型。

注意:如果你正在发布完全编译的框架,而不是框架项目,最终用户并不需要安装任何东西


3、不同框架类型的使用时机

简单来说,你可以这样决定用哪一种框架:
·         如果你不想修改Xcode,那么请使用“伪”框架版本
·         如果你只是想共享二进制(不是项目),两种都可以
·         如果你想把框架共享给不想修改Xcode的开发者,使用“伪”框架版本
·         如果你想把框架共享给修改过Xcode的开发者,使用“真”框架版本
·         如果你想把框架项目作为另一个项目的依赖(通过workspace或者子项目的方式),请使用“真”框架(或者“伪”框架,使用-framework——见后)
·         如果你想在你的框架项目中加入其他静态库/框架,并把它们也链接到最终结果以便不需要单独添加到用户项目中,使用“伪”框架


六、iOS静态框架的创建、编译和使用

1、安装框架模板

要想在xcode中创建静态框架,须得先安装相应的模板iOS Universal Framework Mk

iOS Universal Framework Mk 8的下载地址:https://github.com/kstenerud/iOS-Universal-Framework

解压下载文件,打开Terminal,进入到刚下载文件,Fake Framework下面。输入命令:sh install.sh。同理安装Real Framework下的文件。安装完毕如下图:

我的图片一

分别运行Real Framework目录或Fake Framework目录下的install.sh脚本进行安装(或者两个你都运行)。

重启Xcode,你将在新项目向导的Framework&Library下看到StaticiOS Framework(或者Fake Static iOS Framework)。

若要卸载这两个模板,请运行unistall.sh脚本并重启Xcode

2、  创建一个IOS框架项目

①创建新项目。

②项目类型选择Framework&Library下的Static iOS Framework(或者Fake Static iOS Framework)。

③ 选择“包含单元测试”(可选的)。

④在target中加入类、资源等。

⑤凡是其他项目要使用的头文件,必需声明为public。进入target的Build Phases页,展开Copy Headers项,把需要public的头文件从Project或Private部分拖拽到Public部分。

3、  编译IOS框架、

①    选择指定target的scheme。

②修改scheme的Run配置(可选)。Run配置默认使用Debug,但在准备部署的时候你可能想使用Release。

③编译框架(无论目标为iOS device和Simulator都会编译出相同的二进制,因此选谁都无所谓了)。

④从Products下选中你的framework,“show in Finder”。

build目录下有两个文件夹:(yourframework).framework and (your framework).embeddedframework.

如果你的框架只有代码,没有资源(比如图片、脚本、xibcoredatamomd文件等),你可以把(yourframework).framework 分发给你的用户就行了。如果还包含有资源,你必需分发(your framework).embeddedframework给你的用户。

为什么需要embedded framework?因为Xcode不会查找静态框架中的资源,如果你分发(your framework).framework, 则框架中的所有资源都不会显示,也不可用。

一个embedded framework只是一个framework之外的附加的包,包括了这个框架的所有资源的符号链接。这样做的目的是让Xcode能够找到这些资源

4、  使用静态框架

iOS框架和常规的Mac OS动态框架差不多,只是它是静态链接的而已。

在你的项目中使用一个框架,只需把它拖仅你的项目中。在包含头文件时,记住使用尖括号而不是双引号括住框架名称。例如,对于框架MyFramework

#import <MyFramework/MyClass.h>

七、静态库.a文件的编写

IOS产生.a的静态库,比起.framework相对简单了好些。

 下面介绍一下具体生成步骤:

1、新建一个framework&library库。IOS 下的cocoa touch static library。然后输入product name libsql

 

2、把libsql.hlibsql.m删除。导入ocsqlite.hocsqlite.c(文件见http://blog.csdn.net/fengsh998/article/details/8278978

3、修改scheme,设为release版本。

 

OK,选译ios device编译运行。成功后将在目录的build/products/release-iphoneos/下产生一个liblibsql.a文件。

注,这里产生的是真机使用的.a文件。

选译iphonesimulator 进行编译一次,同样会在build/products/release-iphonesimulator/下产生一个liblibsql.a文件。

这里是虚拟机使用的.a文件。

 

下面来看一下这两个文件有什么不同之处,使用lipo -info命令。

打开终端。

进入到相应的目录。

真机的:liblibsql.a文件信息。

input file liblibsql.a is not a fat file

Non-fat file: liblibsql.a is architecture: armv7

如图:

模拟器的:liblibsql.a文件信息。

input file liblibsql.a is not a fat file

Non-fat file:  liblibsql.a  is architecture: i386

如图:

如果使用真机和模拟器通用,则需要将这两个文件合并,使用命令lipo -create  xxxx/liblibsql.a   xxxxx/liblibsql.a  -output  libsql.a

同样可以使用lipo -info 来查看这个合并的libsql.a

可以看到architectures in the fat file: libsql.a are: i386  armv7

如图:

八、iOS中创建,使用动态库(dylib)

由于苹果不支持自己创建动态库,所以这里需要替换两个文件

iOS Device 需要替换的文件

替换路径:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/Library/Xcode/Specifications/

iOS 模拟器需要替换的文件

替换路径:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Library/Xcode/Specifications

具体可参照:http://blog.iosplace.com/?p=33    或者  http://www.cocoachina.com/bbs/simple/?t129814.html 

替换完成后重启Xcode

创建动态库

 

1:打开Xcode,新建项目,选择OS X --> Cocoa Library -->输入动态库的相关信息

 

2:这样,动态库已经创建好,但是由于此项目是基于Mac OS X创建的,所以这里要将project的相关设置作修改

 

     1:Base  设置成 SDK iOS6.0

 

     2:Architectures  设置成 standrand armv7 armv7s

 

     3:Installation Directory  设置成 @executable_path/

 

     4:Mach-O Type  设置成 Dynamic Library

 

     5:Executable Prefix 设置成 

 

     6:打开项目的project.pbxproj(文本编辑器打开)文件,在编辑器中将producttype 的值修改为 com.apple.product-type.library.dynamic

 

     7:选择合适的证书文件

 

3:debug改为no

4:在动态库的相关类中添加一些测试方法

5:删除多余的framework文件。值添加Foundation.framework文件

 

Xcode--->Preferences--->Locations--->Advanced---->

 

这样基本就可以编译dylib了,但是这里还有一个需要注意的地方。


编译证书的选择


编译分为设备编译(iOS Device模拟器编译(iPad/iPhone Simulator)

在选择设备编译的时候,一定要选择某个有效的开发者证书。否则编译会出错。

相反,选择模拟器编译的时候,不需要选择证书(如果选了证书,也会报错)。

 


如果一切正常,那么在编译后的文件会出现在项目文件夹的Build/Products/.…文件夹中










评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值