一、为什么要使用framework?

我们都知道要部署一个对开发者友好的库需要很小心,不但要包含库本身,还需要包含库中公开引用到的文件,资源,脚本等等。

framework就是苹果提供给开发者以解决Library部署的方案,本质上就是一系列遵循一定标准结构规则的文件夹,包含了使Library可用应该包括的所有东西,但是不幸的是,苹果在ios中禁止使用动态链接库,并在Xcode中移除了创建静态链接库的功能。

所幸的是,在技术上我们仍然让xcode为ios创建framework,只不过需要一点点改动。

并且,用这样的方式创建的framework是被app store所接受的,尽管形式上不同,但是本质上这些framework还是static framework。

二、framework的种类及比较

1.最常见的framework是动态链接framework,但是只有苹果自己可以给ios添加这样的库,所以木有门路去创建使用这样的库。

2.静态链接库除了函数链接的时机不同以外,在使用上合动态链接库基本差异不大,当然因为函数链接时机不同带来的差异其实已经够大了。

3.“伪”框架是通过破解Xcode的目标Bundle(使用某些脚本)来实现的。它在表面上以及使用时跟静态框架并无区别。“伪”框架项目的功能几乎和真实的框架项目没有区别(不是全部)。

4.“嵌入”框架是静态框架的一个包装,以便Xcode能获取框架内的资源(图片、plist、nib等)。

众所周知的是,动态链接库实际上是一种lazy linking的机制,好处在于可以实现进程间的资源共享,以时间换空间,另外大大减小程序编译耦合性,使升级更新更为方便。而静态库由于是在编译时链接函数,所以在运行时没有链接函数的时间成本,运行时性能上会优于动态链接库。

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

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

因此它跟“真”静态框架一样可以正常工作,但当存在依赖关系时就有麻烦了,这个后面使用时来说解决的办法。

三、创建framework

目前网上通用的修改xcode以创建static framework的方法可以参见https://github.com/kstenerud/iOS-Universal-Framework

具体的使用方法,该github页面都有详细说明,这里简单整理一下:

1.framework模板的选择

简单说,你可以这样决定用哪一种模板:

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

2.安装

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

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

卸载请运行unistall.sh脚本并重启Xcode。

3.创建一个iOS框架项目

  1. 创建新项目。
  2. 项目类型选择Framework&Library下的Static iOS Framework(或者Fake Static iOS Framework)。
  3. 选择“包含单元测试”(可选的)。
  4. 在target中加入类、资源等。
  5. 凡是其他项目要使用的头文件,必需声明为public。进入target的Build Phases页,展开Copy Headers项,把需要public的头文件从Project或Private部分拖拽到Public部分

4.编译你的 iOS 框架

  1. 选择指定target的scheme
  2. 修改scheme的Run配置(可选)。Run配置默认使用Debug,但在准备部署的时候你可能想使用Release。
  3. 编译框架(无论目标为iOS device和Simulator都会编译出相同的二进制,因此选谁都无所谓了)。
  4. 从Products下选中你的framework,“show in Finder”。

编译完后, 在build目录下有两个文件夹: (yourframework).framework and (your framework).embeddedframework.

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

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

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

5.使用iOS 框架

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

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

#import <MyFramework/MyClass.h>

四、Trouble Shooting

   

Headers Not Found

如果Xcode找不到框架的头文件,你可能是忘记将它们声明为public了。参考创建一个iOS框架项目5步。

No Such Product Type

如果你没有安装iOS Universal FrameworkXcode,并企图编译一个universal框架项目(对于框架,不是框架),这会导致下列错误:

target specifies product type 'com.apple.product-type.framework.static',but there's no such product type for the 'iphonesimulator' platform

为了编译”iOS静态框架,Xcode需要做一些改动,因此为了编译静态框架项目,请在所有的开发环境中安装它(对于使用框架的用户不需要,只有要编译框架才需要)。

The selected run destination is not valid for this action

有时,Xcode出错并加载了错误的active设置。首先,请尝试重启Xcode。如果错误继续存在,Xcode产生了一个坏的项目(因为Xcode4的一个bug,任何类型的项目都会出现这个问题)。如果是这样,你需要创建一个新项目重来一遍。

链接警告

第一次编译框架target时,Xcdoe会在链接阶段报告找不到文件夹:

ld: warning: directory not found for option'-L/Users/myself/Library/Developer/Xcode/DerivedData/MyFramework-ccahfoccjqiognaqraesrxdyqcne/Build/Products/Debug-iphoneos'

此时,可以clean并重新编译target,警告会消除

Core Data momd not found

对于框架项目和应用程序项目,Xcode会以不同的方式编译momd(托管对象模型文件)。Xcode会简单地在根目录创建.mom文件,而不会创建一个.momd目录(目录中包含VersionInfo.plist.mom文件)。

这意味着,当从一个embedded frameworkmodel中实例化NSManagedObjectModel时,你必需使用.mom扩展名作为modelURL,而不是采用.momd扩展名。

NSURL *modelURL = [[NSBundle mainBundle]URLForResource:@"MyModel" withExtension:@"mom"];

Unknown class MyClass in Interface Builder file.

由于静态框架采用静态链接,linker会剔除所有它认为无用的代码。不幸的是,linker不会检查xib文件,因此如果类是在xib中引用,而没有在O-C代码中引用,linker将从最终的可执行文件中删除类。这是linker的问题,不是框架的问题(当你编译一个静态库时也会发生这个问题)。苹果内置框架不会发生这个问题,因为他们是运行时动态加载的,存在于iOS设备固件中的动态库是不可能被删除的。

有两个解决的办法:

  1. 让框架的最终用户关闭linker的优化选项,通过在他们的项目的Other Linker Flags中添加-ObjC-all_load
  2. 在框架的另一个类中加一个该类的代码引用。例如,假设你有个MyTextField类,被linker剔除了。假设你还有一个MyViewController,它在xib中使用了MyTextFieldMyViewController并没有被剔除。你应该这样做:

MyTextField中:

+ (void)forceLinkerLoad_ {}

MyViewController中:

+(void) initialize {     [MyTextField forceLinkerLoad_]; }

他们仍然需要添加-ObjClinker设置,但不需要强制all_load了。

2种方法需要你多做一点工作,但却让最终用户避免在使用你的框架时关闭linker优化(关闭linker优化会导致object文件膨胀)。

unexpected file type 'wrapper.cfbundle' in Frameworks &Libraries build phase

这个问题发生在把框架项目作为workspace的依赖,或者把它当作子项目时(框架项目没有这个问题)。尽管这种框架项目产生了正确的静态框架,但Xcode只能从项目文件中看出这是一个bundle,因此它在检查依赖性时发出一个警告,并在linker阶段跳过它。

你可以手动添加一个命令让linker在链接阶段能正确链接。在依赖你的静态框架的项目的OtherLinker Flags中加入:

-framework MyFramework

警告仍然存在, 但不会导致链接失败。

Libraries being linked or not being linked into the finalframework

很不幸, 框架和框架模板在处理引入的静态库/框架的工作方式不同的。

框架模板采用正常的静态库生成步骤,不会链接其他静态库/框架到最终生产物中。

框架模板采用欺骗”Xcode的手段,让它认为是在编译一个可重定位格式的目标文件,在链接阶段就如同编译一个可执行文件,把所有的静态代码文件链接到最终生成物中(尽管不会检查是否确实目标代码)。为了实现象框架一样的效果,你可以只包含库/框架的头文件到你的项目中,而不需要包含库/框架本身。

Unrecognized selector in (some class with a category method)

如果你的静态库或静态框架包含了一个模块(只在类别代码中声明,没有类实现),linker会搞不清楚,并把代码从二进制文件中剔除。因为在最终生成的文件中没有这个方法,所以当调用这个类别中定义的方法时,会报一个“unrecognizedselector”异常。

要解决这个,在包含这个类别的模块代码中加一个假的类。linker发现存在完整的O-C类,会将类别代码链接到模块。

我写了一个头文件LoadableCategory.h,以减轻这个工作量:

#import "SomeConcreteClass+MyAdditions.h"

#import "LoadableCategory.h"  MAKE_CATEGORIES_LOADABLE(SomeConcreteClass_MyAdditions);   @implementation SomeConcreteClass(MyAdditions)

...

@end

在使用这个框架时,仍然还需要在Build SettingOther Linker Flags中加入-ObjC

执行任何代码前单元测试崩溃

如果你在Xcode4.3中创建静态框架(或库)target时,勾选了“withunit tests”,当你试图运行单元测试时,它会崩溃:

Thread 1: EXC_BAD_ACCESS (code=2, address=0x0) 0 0x00000000 --- 15 dyldbootstrap:start(...)

这是lldb中的一个bug。你可以用GDB来运行单元测试。编辑scheme,选择Test,在Info标签中将调试器DebuggerLLDB改为GDB

转载于:https://my.oschina.net/xiguaa/blog/146434

Xcode 打包 framework相关推荐

  1. xcode 打包framework时去除某些架构

    下图所示为编译后的.framework文件: 已知该.framework支持的真机架构为arm64和armv7两种.现在想要缩小framework库的容量,只保留arm64架构.Terminal中运行 ...

  2. iOS 打包.framework(包括第三方、图片、xib、plist文件)详细步骤及需要注意的地方...

    https://www.cnblogs.com/yk123/p/9340268.html // 加载自定义名称为Resources.bundle中对应images文件夹中的图片 // 思路:从main ...

  3. Xcode打包上传时,最后一步出现An error occurred uploading to the iTunes Store.的解决方法...

    本人最近提交包的时候到最后一部出现以下提示: An error occurred uploading to the iTunes Store. 解决方法: 打开终端,输入以下命令 1.cd ~ 2.m ...

  4. 使用XCode打包ipa

    使用XCode打包ipa 1.选择 Edit Scheme 2.选择Build Configuration的[Release] 3.按住Command + B ,进行编译 通过前面指定的Release ...

  5. xcode打包IPA上架App Store图文详解

    2017年最新整理的xcode打包IPA上传App Store完整教程,帮助新手们快速掌握ios上架流程! 分为8 步进行 1.申请iOS证书 2.导入证书到钥匙串 3.xcode配置iOS证书 4. ...

  6. xcode打包bundle资源在unity上导入的时候出现Could not create asset from XXXX.png: File could not be read

    我xcode打包的bundle资源在unity上导入的时候出现Could not create asset from XXXX.png: File could not be read,排查了蛮久才发现 ...

  7. Xcode 打包动态及静态Framework

    参考链接:http://www.cocoachina.com/ios/20141126/10322.html 作者: suiling

  8. [绍棠] ijkplayer 的编译、打包 framework 和 https 支持

    ijkplayer是 bilibili开源的一款优秀的播放器, 基于 FFmpeg, 支持 iOS/Android, 点播/直播, 以及多种编码. 官方并不直接提供 framework 框架包, 这样 ...

  9. xcode打包(Archive)显示Command /usr/bin/codesign failed

    2019独角兽企业重金招聘Python工程师标准>>> 打包错误提示截图如下: 分析错误提示,显示的是证书和配置文件有提问,提示是没有到.根据此提示,我到开发者网站查看,发现证书没有 ...

  10. iOS打包framework - Swift完整项目打包Framework,嵌入OC项目使用

    场景说明: -之前做的App,使用Swift框架语言,混合编程,内含少部分OC代码. -需要App整体功能打包成静态库,完整移植到另一个App使用,该App使用OC. -所以涉及到一个语言互转的处理, ...

最新文章

  1. Windows7无法自动将IP协议堆栈绑定到网络适配器的办法
  2. 剑指offer:面试题37. 序列化二叉树
  3. Beta 冲刺(5/7)
  4. Unity3D-RayMarch-几何图元0
  5. 【HAOI2015】树上染色
  6. 第一次团队作业——团队展示
  7. halcon/c++接口基础 之 析构函数和Halcon算子
  8. 为什么我不推荐你使用vue-cli创建脚手架?
  9. 如何计算边缘计算的成本
  10. dll.dll病毒及解决办法
  11. 发送邮件服务器错误怎么更改,怎么解决SMTP服务器发送邮件失败
  12. 能上天的代码? NASA 火星无人机飞行控制系统开源了
  13. DHZT_ROS_Developer_Guide 大华中天ROS风格指南
  14. torch.nn到底是什么?(精简版)
  15. Jackie Chan Comments Spark Online Backlash
  16. 亚马逊运营面试经验分享:避免踩坑,少走弯路
  17. java发送邮件格式_java使用main函数进行邮件发送怎样设置邮件格式
  18. Druid关闭监控页面及设置密码
  19. 通用Nginx优化配置
  20. Android修行手册 - Toolbar实践

热门文章

  1. 配置STP、RSTP以及负载均衡
  2. PHP 工厂模式浅析
  3. python 装饰器,登录小练习
  4. 网络爬虫的基本原理(一)
  5. CSS3 圆形时钟式网页进度条
  6. EasyUI常用控件禁用方法
  7. 【深度解析】Google第二代深度学习引擎TensorFlow开源
  8. css设置自适应屏幕高度
  9. 【转】Perl、PHP、Python、Java和Ruby的比较
  10. poj 1753 Flip Game (高斯消元 + 枚举 自由变量)