pod pod 发布frameworkk 打包不包含资源文件

> xcode静态库资源文件及xib打包
xcode静态库资源文件及xib打包
ljc0651 & &
发布时间: & &
浏览:115 & &
回复:0 & &
悬赏:0.0希赛币
xcode 静态库资源文件及xib封装目前有个需求,需要把.xib封装到静态库中,试了很多种方法都不行,最后看到这篇文章&,它是从&iOS
Library With Resources&翻译过来的,图片没有显示(原文有)。
  这里主要是把静态库种的.xib封装到bundle中,然后把静态库内链到工程中。
  以下是这篇文章主要流程:
  1&添加资源Bundle Target
  资源必须是单独编译成Bundle才能使用,所以需要为MyLibrary(静态库target)项目生成另一个Bundle Target
  选择MyLibrary(静态库target)项目,在右边面板中点Add Target-&MAC OS X-&FRAMEWORK &LIBRARY-&Bundle
  需要说明,bundle项目只有MAC OS X里才有,但实际上也是可以用于IOS的,只是需要做些改动,即下面的第2步.
  2&修改资源bundle target
  把bundle target修改成ios能用的,看图
  Build Settings设置
  1)Architectures为Standard (armv7)
  2)Build Active Architecture Only 为指定的IOS版本
  3&添加 XIB的输出
  设置XIB为输出到BUNDLE,这一步相当于VS c#开发里把某个图片设置编译动作为嵌入资源.
  选择Mylibrary(静态库target)项目,targets选择MyLibraryResources(静态库资源target),Build Phases面板
  Copy Bundle Resources点+选择xib文件
  4&关联静态库引用
  把主程序和静态库做关联,这样省得每次要手动添加静态库的.a文件
  要说明下:我原本以为编译主程序会自动编译静态库,实际上做的并没有那么好,我改动了静态库的XIB内容,但编译主程序后发现内容还是上次的,所以我每次都是clean build.
  编辑Scheme(菜单Product-&Edit Scheme)
  选择Build
  点+,选择MyLibrary(静态库target)和MylibraryResources(静态库资源target)项目
  这样的话,每次build都可以编译多个target和scheme。
  5&最后设置主程序项目
  选择MyLibraryResource(静态库资源target)项目在Build Settings面板里
  设置User Header Search Paths为$(BUILT_PRODUCTS_DIR),注意建议把Recursive勾上(递归搜索)
  6 使用&
  选择要使用静态库的工程,target-&build phases-&copy bundle
resources,点击&+&,add other 添加MylibraryResources.bundle,一般在build-&release-iphoneos目录。
  重写controller的init
  ResourcesBundle=资源文件bundle
  - (id)init
  NSBundle&*bundle
= [NSBundle&bundleWithURL:[[NSBundlemainBundle]&URLForResource:ResourcesBundlewithExtension:@&bundle&]];
  if&((self&=
[super&initWithNibName:[NSStringstringWithUTF8String:object_getClassName(self)]&bundle:bundle]))
  //code
关于xib中的图片
  如果xib中有图片,可能会报以下的警告,然后图片显示不成功。
  Could not load the image 'xxx.png' referenced from a nib in the bundle with identifier &com.xxx.xxx&
  解决方法:
  手动指定xib中的图片
本问题标题:
本问题地址:
温馨提示:本问题已经关闭,不能解答。
暂无合适的专家
&&&&&&&&&&&&&&&
希赛网 版权所有 & &&给 Pod 添加资源文件 - 闲趣
注:本文假定读者对 CocoaPods 的使用已经相当熟练,创建过 Pod 或有此打算。
是当前 Swift 和 Objective-C 工程中较为流行的依赖管理工具。它拥有超过 10,000 个程序库,通过一份 Podfile 和几条基本命令就能帮助开发者优雅地管理工程依赖。
虽然人们绝大多数时候只是利用 CocoaPods 安装或更新特定版本的库,但是在应用开发过程中,难免会遇到需要自己创建 pod 的情况。CocoaPods 规定每个 pod 库都必须要有一份 podspec 文件。在这份文件里,你要填写作者信息、功能简介、版权信息等基本内容。具体语法可以参看。
在 podspec 中,利用 source_files 你可以指定要编译的源代码文件。可是,当你需要把图片、音频、NIB等资源打包进 Pod 时该怎么办呢?我“有幸”在做 pod 时踩过几个和资源文件有关的坑,在此和大家分享。
1. resources or resource_bundles
有经验的同学在我提出怎么在 pod 中打包资源这个问题时,肯定会告诉我 resources 这个属性。示例用法如下:
spec.resources = [&Images/*.png&, &Sounds/*&]
我们在 Cocoa 社区见到的绝大多数库都在用它。利用 resources 属性可以指定 pod 要使用的资源文件。这些资源文件在 build 时会被直接拷贝到 client target 的 mainBundle 里。这样就实现了把图片、音频、NIB等资源打包进最终应用程序的目的。
但是,这就带来了一个问题,那就是 client target 的资源和各种 pod 所带来的资源都在同一 bundle 的同一层目录下,很容易产生命名冲突。例如,我的 app 里有张按钮图片叫 &button.png&,而你的 pod 里也有张图片叫 &button.png&,拷贝资源时,我很担心 pod 里的文件会不会把我 app 里的同名文件给覆盖掉?即使没覆盖掉,程序运行时到底用哪张?很显然,我们不希望上述事情发生。
为了解决这一问题,CocoaPods 在 0.23.0 加入了一个新属性 resource_bundles。示例用法如下:
spec.resource_bundles = {
'MyLibrary' =& ['Resources/*.png'],
'OtherResources' =& ['OtherResources/*.png']
可见, resources 和 resource_bundles 的差别是在于后者用字典替换了数组。相较之前所有资源都平铺开来的做法,新属性显式地做了 bundle 层面的分组。有组织、有纪律!CocoaPods 官方显然更推荐 resource_bundles。原因有二:
如前所述,用 resources 属性容易引起资源的命名冲突。诚然, resource_bundles 也有极小的可能在 bundle 名上起冲突,可那也比前者好处理。
用 resources 属性指定的资源直接被拷贝到 client target(事实上 CocoaPods 会先运行脚本对 NIB,Asset Catalog,Core Data Model 等进行编译),这些资源无法享受 Xcode 的优化。这是官方文档的说法,但不清楚所指的优化是哪些(图片压缩?)
即便如此,那为什么还有很多开源产品依然在用 resources 属性呢?
历史遗留问题。早些年用了这属性,现在运行也好好的,就不动了吧。
随大流。貌似大家都这么用,应该是正确的,我也这么弄吧,懒得去看文档,抄抄改改呗。
咱有奇技淫巧。
很多库在 podspec 里其实是这么写的。
spec.resource = &Resources/MYLibrary.bundle&
把资源加到形如 MYLibrary.bundle 的 bundle 里。这样就使得 client target 资源在 mainBundle 根目录下,而各个 Pod 的自带资源则在外面套了个 bundle 后再被拷贝到 mainBundle 里,机智地解决了冲突√。
还有一种解决方案,那就是在 Objective-C 开发中常见的加前缀法,即对每项资源加前缀。跟我一起说:NS大法好!
当然,我还是建议大家照着 CocoaPods 推荐的来。
2. 访问 bundle
在 CocoaPods 0.36 以前,pod 资源最后都会被直接拷贝到 client target 的 [NSBundle mainBundle] 里。你可以用访问 mainBundle 里资源的方式访问它们。比如用 + (UIImage *)imageNamed:(NSString *)name 来访问 pod 的图片。
但是在 CocoaPods 0.36 之后,这件事情发生了一些变化。由于 iOS 8 Dynamic Frameworks 特性的引入,CocoaPods 能帮你打包 framework 了(撒花)。很详细地说明了加入 framework 特性所带来的变化。一个显著区别就是当你的 pod 库以 framework 形式被使用时,你的资源不是被拷贝到 mainBundle 下,而是被放到 pod 的最终产物—— framework 里。此时,你必须保证自己在访问这个 framework 的 bundle,而不是 client target 的。
[NSBundle bundleForClass:&#ClassFromPodspec#&]
上面这段代码可以返回某个 class 对应的 bundle 对象。具体的,
如果你的 pod 以 framework 形式被链接,那么返回这个 framework 的 bundle。
如果以静态库(.a)的形式被链接,那么返回 client target 的 bundle,即 mainBundle。
但无论以哪种形式链接,在这个方法返回的 bundle 下都有你的 pod 资源。接下来要做就是去访问他们。我写了个简单的 category来获取 MyLibrary 的 bundle 对象。
spec.resource_bundles = {
'MyLibrary' =& ['your/path/to/resources/*.png'],
@implementation NSBundle (MyLibrary)
+ (NSBundle *)my_myLibraryBundle {
return [self bundleWithURL:[self my_myLibraryBundleURL]];
+ (NSURL *)my_myLibraryBundleURL {
NSBundle *bundle = [NSBundle bundleForClass:[MYSomeClass class]];
return [bundle URLForResource:@&MyLibrary& withExtension:@&bundle&];
逻辑很简单:先拿到最外面的 bundle。 对 framework 链接方式来说就是 framework 的 bundle 根目录,对静态库链接方式来说就是 target client 的 main bundle,然后再去找下面名为 MyLibrary 的 bundle 对象。
题外话,新的 bundle 策略利用 framework 的命名空间,有效防止了资源冲突。同时对 client 来说,他不需要为 framework 里的资源设置 build rules,如 storyboard,xib一类需要编译的东西,缩短了编译时间,毕竟 framework 里的资源不需要 client 每次都编译了。我觉得很不错。
3. 图片资源
前面我们已经讨论过资源被放到不同 bundle 所带来的访问方式的不同。这次说一下图片的坑,毕竟它们是最常见的资源之一。
一般的图片访问
还是针对 resource_bundles。
spec.resource_bundles = {
'MyLibrary' =& ['your/path/to/resources/*.png'],
写了一个方便访问 pod 图片的 category。
#import &UIImage+MyLibrary.h&
#import &NSBundle+MyLibrary.h&
@implementation UIImage (MyLibrary)
+ (UIImage *)my_bundleImageNamed:(NSString *)name {
return [self my_imageNamed:name inBundle:[NSBundle my_myLibraryBundle]];
+ (UIImage *)my_imageNamed:(NSString *)name inBundle:(NSBundle *)bundle {
#if __IPHONE_OS_VERSION_MIN_REQUIRED &= __IPHONE_8_0
return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil];
#elif __IPHONE_OS_VERSION_MAX_ALLOWED & __IPHONE_8_0
return [UIImage imageWithContentsOfFile:[bundle pathForResource:name ofType:@&png&]];
if ([UIImage respondsToSelector:@selector(imageNamed:inBundle:compatibleWithTraitCollection:)]) {
return [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil];
return [UIImage imageWithContentsOfFile:[bundle pathForResource:name ofType:@&png&]];
+ imageNamed:inBundle:compatibleWithTraitCollection: 这个方法 iOS 8 才加入的,所以做了条件编译。+ imageWithContentsOfFile: 没有缓存机制不开心。当然,如果你坚持用 resources 把自己的资源被拷贝到 main bundle 下,然后直接用 + imageNamed:的话,我敬你是条汉子。
Asset Catalog
理论上一个 bundle 里可以有一个 asset catalog。Xcode 最后会把它们编译成 Assets.car 文件。
我觉得把 pod 的图片扔到 asset catalog 里,然后把 MyLibraryImages.xcassets 放到 resource_bundles 里,也能在代码里通过一定办法访问到图片对象。然而我尝试了各种姿势,依然无法解锁该成就。反倒是用 resources 属性可以成功,匪夷所思。
Google 一圈后在 CocoaPods 的 issue 里发现了,然后 StackOverflow 上又。我也犯迷糊了。
现在想到的临时解决方案是,如果你用 resources 属性指定资源,那么把图片放到 asset catalog 后,用下列方式是可以拿到图片的。
NSBundle *bundle = [NSBundle bundleForClass:[MYClass class]];
UIImage *image = [UIImage imageNamed:name inBundle:bundle compatibleWithTraitCollection:nil];
而如果你用 resource_bundles 属性指定资源,请把图片从 asset catalog 里拿出来裸奔。
希望大家能指点一二,拜谢!
4. 国际化和本地化
做过国际化和本地化的同学都知道在代码里用 NSLocalizedString(key, comment) 来代替一般的字符串做国际化。通过在各种以.lproj结尾的目录下创建 Localizable.strings 文件提供字符串键值对来做本地化。
对一个 pod 来说,如果要提供给 client 本地化资源,其流程也是类似的。不同的地方在于,你最好以 pod 名来命名字符串文件,比如 MyLibrary.strings。此外,在做国际化时要把 NSLocalizedString(key, comment) 换成 NSLocalizedStringFromTableInBundle(key, tbl, bundle, comment),毕竟你的这些本地化资源也要跟着 bundle 走。其中 tbl 就是你 pod 的本地化字符串文件名,如例子是 MyLibrary。
我们可以用一个宏定义来简化工作。
#define MYLibraryLocalizedString(key, comment) \
NSLocalizedStringFromTableInBundle((key), @&MyLibrary&, [NSBundle my_myLibraryBundle], (comment))
把原先的 NSLocalizedString(key, comment) 替换成 MYLibraryLocalizedString(key, comment) 就行了。好奇心强的同学不妨深入看看这些宏定义最后到底是些什么东西。
剧透一下,NSLocalizedString(key, comment) 的本质就是 NSBundle 的 - localizedStringForKey:value:table: 方法。
为什么没效果
当你满心欢喜地在代码里完成了国际化,把本地化字符串也翻译好了,运行程序,发现里面语言愣是只有英文,你怎么想?key 写错了?没有。文件名没弄对?也不是。停停停,请先检查以下几点:
请检查你的设备是否已经设置为你要测的语言;
请确保你在工程层面也声明了要做本地化。具体的,点开 Project 设置,点到 Info 一栏,看看 Localization 那块有没有加对应的语言。
请确保你在添加新文件后运行了 pod update 命令。(写 pod 遇到的各种二逼问题多半因为没跑这条命令)
踩我已经坑了,谁再猜谁二逼。倘若你也在开发过程中踩过奇奇怪怪的坑,欢迎告诉我。至少……能让这世界少点二逼吧……你说呢?场景说明:
-之前做的App,使用Swift框架语言,混合编程,内涵少部分OC代码。
-需要App整体功能打包成静态库,完整移植到另一个App使用,该App使用OC。
-所以涉及到一个语言互转的处理,以及一些appdelegate的代码减除变化。
-----------------------------------------打包篇-----------------------------------------
实现步骤:
一、新建 Project - Framework&Library - Cocoa Touch Framework,Next 语言选择Swift
建立完成,会看到默认生成的一个 &xxx.h 和 &Info.plist &文件。
xxx.h 文件的作用是整个包对外提供的入口头文件,除了正常定义参数属性之外,还有
1、提供给Swift项目内引用的OC文件的import引用,注意,这里引用之前必须在Build Phrases的Headers内暴露到 Public,如图:
2、提供给第三方文件的import,这里的第三方管理,依然是使用Pods管理,下文会具体描述。
以上两部完成效果,如图:
info.plist&文件的作用就如同正常项目的plist文件作用,用来定义或添加一些属性。
二、添加文件,这里可以自己新建,或者从其他项目拷贝过来都可以。
这里要注意一下:由于打包类库工程不是一个完整项目工程,所以并没有AppDelegate等文件,所以涉及到这些的文件要额外处理,或改代码,或适当改变功能。
注意:工程如果有桥接文件,是不能拷贝过来的,否则编译不通过。
原因见步骤五。
三、如果有第三方类库引用,添加第三方库文件,有几个注意点:(没有可以跳过)
a、第三方库依然使用Pods进行管理,添加方法同正常项目一样。
b、引用的时候,我们需要添加 【use_frameworks!】来告诉pod 生成动态库文件Framework类型,这样做的好处是在正式项目用到本类库的时候,如果两者第三方库有引用冲突,可以根据冲突类库,对本类库引入的这些依赖库进行移除。
但有时第三方类库只有 .a 类型的,怎么办?
解决:如果第三方库只有.a类型,就需要手动把库文件拷贝到项目,而不能通过pod添加,否则在往步骤1内的头文件添加import时会找不到文件,从而报错。
四、以上三部做完,基本本类库的雏形已经具备了,参考如下:
这里涉及到一个资源文件的问题,比如图片、视频、音频等的处理。
之前正常项目的做法可能是这样,
1:直接用Assets.xcassets
2:新建resources文件夹,存放图片
但这里,需要注意一点:
对于1,这样做是无效的,我们可以新建一个bundle文件,将图片移植过来。
对于2,我们可以在本地,直接修改添加后缀.bundle
然后一个重点就是路径问题:由于类库的资源文件,当我们在正式项目使用时,查找的路径文件不是针对项目,而是针对类库的路径,所以我们这里引用的资源文件路径都要改变一下,而且类库里的其他xib、storyboard文件引用路径都需要更改一下。
resourceRooturl是xib、storyboard文件前缀路径。
resourceImagesRooturl是图片文件前缀路径。(需要添加一层/images.bundle/)
这个路径怎么来的呢?
Frameworks/XXXX.framework/ & & 其中XXXX就是你建立的类库名称。
引用截图参考:
五、文件都基本添加完毕,可以尝试build一下了
理论上,只要类库默认的xxx.h文件内,oc的头文件和第三方头文件都正常引用了,就不会有问题。
而且一般报错,也都是因为这里没做好的缘故。
如果项目都是纯swift文件,这里xxx.h文件只需要导入第三方头文件即可。
=======================这里解释一下,xxx.h文件为什么要这样做:=================
因为正常我们swift项目,如果需要引入oc文件,我们必须通过一个桥接文件来处理两者之间的转换,而我们在新建类库的时候,类库是禁止这个文件存在的,即使你添加了,也会永远编译不过,打包不了。
所以这里就用到这个类库默认生成的 xxx.h头文件了。
我们可以通过这个文件来实现两者之间的转换,前提就是必须先将oc的.h暴露出来,否则即使你import,也会报错找不到.h 文件。
(这里有个问题,如果oc文件过多,这里需要暴露的就很多,而这里太多的话,一个是不美观,第二是后面项目引用本类库都是能看到这些文件的。所以,能不能通过一个文件,来装载这些所有文件,达到只需要一个文件暴露就行的效果,有人实现了欢迎指导一下,不甚感激。)
六、编译通过,查看这里
红框内就是最终我们得到的Framework包。
右击本地查看,会看到本类库以及对应的依赖第三方包,后面在其他项目引用的时候,这些都是需要的。
PS:如果没有引用第三方,这里只需要本类库包即可。
&-----------------------------------------引用篇-----------------------------------------
1、我们新建一个空的工程,由于我的业务需要,这里工程语言选择OC。
2、新建Framework文件夹,拷贝之前所有的framework包到文件夹内。
3、在工程Targets-General-EmbeddedBinaries内添加Frameworks包
4、由于我的类库包是基于swift建立的,这里oc使用的话,必须设置一个属性:
5、由于我们自己的工程都有自己的第三方库引用,这里如果发现两者之间有冲突或重复引用,解决如下:
a:如果pod引用内,没有标注 &use_frameworks! & &我们先加上这句话,并pod update,目地是保持两边引用的第三方类库都是Framework类型。
b:移除刚才添加过来中的重复类库,比如AFN
这里引用集成时我遇到的坑如下:
==================================报错1:==================================
dyld: Library not loaded: @rpath/AFNetworking.framework/AFNetworking
这里是因为只引用了之前的类库本身,没有将类库自身的依赖库一并引用过来,
解决办法:
按照我的引用篇-步骤3去做,在general处,全部添加,就不会报这个问题。
&==================================报错2:==================================
&dyld: Library not loaded: @rpath/libswiftCore.dylib&
解决办法:
按照我的引用篇-步骤4去做&,设置属性为Yes。
Xcode8升级之后属性名称有所变化:
参考这篇:/yajunLi/p/5979621.html
&==================================报错3:==================================
&&Unknown class in Interface Builder file .... image not &found 等
解决办法:
/yajunLi/p/5980560.html
&==================================报错4:==================================
load &storyboard 或xib &崩溃
解决办法:
是因为打包的地方引用文件路径没有改动,需要加上类库前缀路径,详见打包篇-步骤四。
&----------------------------打包合并真机和模拟器------------------------------
详细见我另一篇文章:
/yajunLi/p/6005077.html
若还有其他问题欢迎留言。
本文结束。
阅读(...) 评论()4934人阅读
问题的提出:
随着项目的越来越大,可能会出现好几个团队共同维护一个项目的情况,例如:项目组A负责其中的A块,项目组B负责其中的B块.....这几块彼此之间既独立,也相互联系.对于这种情况,可以采用约定的方式,比如,你只修改你那块,不要修改公共的.如果要修改公共的,那么必须要通知一下其它组,大家共同决定怎么修改,这种方式有一个很大的问题,很有可能不经意间就改了别的团队的代码.还有维护的越来越复杂等.
诸如此类的问题,很自然的我们会考虑每个团队建立一个静态库
&IOS的静态库有两种,.a和.framework, &动态库.framework居多. & 静态库建议也生成.framework模式的,好处是.framework包含了相关的.h文件等..a文件还要自己添加相关的.h文件
&& 静态库:链接时,静态库会被完整地复制到可执行文件中,被多次使用就有多份冗余拷贝.例如我们在我们的程序中使用了百度地图的.a文件,另外一个应用也使用了百度地图.a.这样整个系统中,会出现两个 百度地图.a文件
&& 动态库:链接时不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存.系统提供的库基本上都属于此类,例如UIKit等,A应用和B应用中都用到了UIKit,系统只加载了一份在内存中.IOS中对于第三方的动态库,很遗憾,目前还不支持的.
一:framework的制作
& &从xcode6开始,已经提供了制作.framework的选项了
下面我们用系统自带的来新建.framework.然后再添加一个依赖库 AFNetworking
1) xcode的菜单栏 &File -& New Project &建立一个名为 &YohunlUtilsLib 的Cocoa Touch Framework的工程. 将Target 改为 7.0(由于现在大多数应用都还要支持7.0sdk,故此处我们修改为支持7.0)
这时候,编译一下,你可能会遇到警告 &
& & & & & (null):&Embedded&dylibs/frameworks&only&run&on&iOS&8&or&later
别着急,这个是由于 从IOS8开始,建立的framework可以是动态的(并不是完全意义上的动态,这里的动态,其实还是要嵌入到我们的应用中,而不能够从网上下载,然后用dlopen动态加载的).
我们要修改 Mach-O Type.从默认的Dynamic Library 改为 Static Library,再编译,警告消失
那么选择&Dynamic Library 还是 & Static Library 有什么影响呢? 我已经实际的检验过了.(我采用了一个包含了 第三方库 AFnetworking的测试工程)
& Static Library 支持IOS8.0 sdk以下的,从目前来看,大多数工程都还要支持7.0 sdk,所以我们最常用的就是Static Library &
当我们使用 & Static Library时候,生成的framework直接如同添加普通文件的形式添加进来就可以了.它会自动在
不过当我们运行的时候,会提示:
当生成后,添加到示例工程中,
好吧,这种模式的添加,看来有些问题呀,还要自己添加依赖库,这些依赖库都是系统的,根据提示自己添加就可以了
当我们使用 Dynamic Library模式(只有IOS8.0及以上才支持)的时候.如同普通文件一样添加到示例工程中去的话,运行,会出现提示:
dyld: Library not loaded: @rpath/NetTestLib.framework/NetTestLib
& Referenced from: /Users/yohunl/Library/Developer/CoreSimulator/Devices/B1DBCA26-C113-4C74-BB81-297D4AF1E0C8/data/Containers/Bundle/Application/C1B4F6D5-96FD-D-4F1C569EEF6F/TestFramework.app/TestFramework
& Reason: image not found
解决的方式&
在工程的配置 &Embedded Binaries下面添加.而不是在 Linked Frameworks and Libraries下添加.这种方式,不需要添加 AFNetworking所需要的系统库,这一点不知道是什么原因!!!如果有知道原因的,请也告知我一下啊
2) &命令行,进入目录下 &pod init 建立一个podfile文件,因为我们制作的.framework需要用到AFNetworking网络库 PS:你也可以用任意的方式建立这个podfile文件
& & 打开它,因为我采用 pod init命令建立的,打开后你会发现它已经有内容了
修改其内容为
& & & & & & & & & &platform&:ios,&'7.0'
& & & & & & & & & &inhibit_all_warnings!
& & & & & & & & & target&'YohunlUtilsLib'&do
& & & & & & & & & & & & pod&'AFNetworking'
& & & & & & & & & end
& & & & & & & & & target&'YohunlUtilsLibTests'&do
& & & & & & & & & end
再执行 pod install 建立依赖
打开工程,添加一个文件 &YONetwork.h,在其中添加方法
@interfaceYONetwork :NSObject
获取github上用户的repo
&*& @paramuser&&&用户名
&*& @paramsuccess成功的回调
&*& @paramfailure失败的回调
- (void)getGithubReposForUser:(NSString*)user
withSuccess:(void(^)(idresponseObject))success
failure:(void(^)(NSError*error))
测试 getGithubReposForUser:withSuccess:failure的
#import&YONetwork.h&
&AFNetworking.h&
@implementationYONetwork
- (void)getGithubReposForUser:(NSString*)user
withSuccess:(void(^)(idresponseObject))success
failure:(void(^)(NSError*error))failure
AFHTTPRequestOperationManager
*manager = [AFHTTPRequestOperationManagermanager];
&&& [manager
GET:[NSStringstringWithFormat:@&/users/%@/repos&,
parameters:nilsuccess:^(AFHTTPRequestOperation*operation,id
responseObject) {
&&&&&&& success(responseObject);
failure:^(AFHTTPRequestOperation*operation,NSError*error)
&&&&&&& failure(error);
- (void) test {
&&& [selfgetGithubReposForUser:@&yohunl&withSuccess:^(idresponseObject)
NSLog(@&getGithubReposForUser response = %@&,responseObject);
failure:^(NSError*error) {
NSLog(@&getGithubReposForUser error = %@&,error);
编译运行 (command + B),生成相应的.framework文件&
菜单 - &organizer&
可以看到目录结构如下:
其中的&YohunlUtilsLib.framework 就是我们要的 &: 注意,YohunlUtilsLib.framework中并没有包含AFNetworking库的内容,这一点我们可以用如下的命令来验证.
命令进入 Debug-iphoneos
$ lipo -info YohunlUtilsLib.framework/YohunlUtilsLib
Architectures in the fat file: YohunlUtilsLib.framework/YohunlUtilsLib are: armv7 arm64
说明我们生成的真机framework:YohunlUtilsLib.framework 包含了两种架构&armv7
分离出每一种架构
$ mkdir armV7 &当前目录建立文件夹,用于存放分离后的架构,和分离出的.o文件
$ lipo YohunlUtilsLib.framework/YohunlUtilsLib -thin armv7 -output ./armv7/YohunlUtilsLib_armv7 &分离出armv7架构到文件夹armV7下
$ cd armV7 进入文件夹
$ ar -x YohunlUtilsLib_armv7 &分离出armv7架构的所有的.o文件
分离后,如图:
可以看到,最后的.framework中,并没有包含我们pod添加的 AFNetworking.所以 当我们把我们生成的YohunlUtilsLib.framework给别人使用过的时候,别人自己要在项目中添加
AFNetworking,否则会提示找不到的错误.&
&验证的方式可以参见&& 主要是利用命令 &&
3) 我们使用命令来合并我们生成的真机和模拟器的framework
建立一个新的target
target建立后
添加如下的合并模拟器和真机的脚本
# Constants
SF_TARGET_NAME=${PROJECT_NAME}
#自定义的用来存放最后合并的framework
UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal
#IPHONE_DEVICE_BUILD_DIR=${BUILD_DIR}/${CONFIGURATION}-iphoneos
WORKSPACE_NAME=${PROJECT_NAME}.xcworkspace
YO_SCHEME=${PROJECT_NAME}
#clean build是先清除原来的build
xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphonesimulator -configuration&${CONFIGURATION}&clean build
xcodebuild -workspace ${WORKSPACE_NAME} -scheme ${YO_SCHEME} -sdk iphoneos -configuration&${CONFIGURATION}&clean build
# build project
#xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphoneos BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}&
CONFIGURATION_BUILD_DIR=&${IPHONE_DEVICE_BUILD_DIR}/arm64& SYMROOT=&${SYMROOT}& ARCHS='arm64' VALID_ARCHS='arm64' $ACTION
#xcodebuild -project &${PROJECT_FILE_PATH}& -target &${TARGET_NAME}& -configuration &${CONFIGURATION}& -sdk iphoneos BUILD_DIR=&${BUILD_DIR}& OBJROOT=&${OBJROOT}& BUILD_ROOT=&${BUILD_ROOT}&&
CONFIGURATION_BUILD_DIR=&${IPHONE_DEVICE_BUILD_DIR}/armv7& SYMROOT=&${SYMROOT}& ARCHS='armv7 armv7s' VALID_ARCHS='armv7 armv7s' $ACTION
# Copy the framework structure to the universal folder (clean it first)
#因为framework的合并,lipo只是合并了最后的二进制可执行文件,所以其它的需要我们自己复制过来
#先移除原来的
&${UNIVERSAL_OUTPUTFOLDER}&
&${UNIVERSAL_OUTPUTFOLDER}&
&${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework&
&${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework&
#合并模拟器和真机的架构
lipo -create&
&${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework/${PROJECT_NAME}&&${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework/${PROJECT_NAME}&-output&${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework/${PROJECT_NAME}&
&${UNIVERSAL_OUTPUTFOLDER}&
对于以上的脚本,其中用到了很多的 xcode预定义的变量,这些变量怎么来的呢?你可以在命令行下, 输入
xcodebuild -workspace YohunlUtilsLib.xcworkspace -scheme YohunlUtilsLib -sdk iphonesimulator -configuration Debug -showBuildSettings & xcodebuild_showBuildSettings.txt
来将所有的xcode预定义变量都导入到文本xcodebuild_showBuildSettings.txt 中,然后你就可以选用你需要的啦
当然了,我们一般都应该合并release模式的,而不是debug模式的framework,这个可以在
ccmmand+B 编译
如果不出错的话,应该会弹出
到此处,我们的framework建立好了,下面可以建立一个测试工程来测试一下,是否可以了
4)建立一个single View Application的测试上述framework的工程&TestFrameworkDemo
将上一步生成的&Release-universal/YohunlUtilsLib.framework 加入到工程&TestFrameworkDemo
再写一个测试用例:
运行,这时候,你会收到错误提示
还记得前面说过吧,我们打包的framework并不包含
此时,我们有两种方式解决这个问题:
&1. 将我们生成&YohunlUtilsLib.framework 过程中生成的libAFNetworking.a 拷贝过来,添加到工程中(当然了,你要自己合并 libAFNetworking的真机和模拟器的.a文件) [这种方式的好处是可以保证我们的YohunlUtilsLib.framework使用到的libAFNetworking和我们一样的版本,保证了兼容性,,但同时也增加了集成的复杂性,我们要申明我们的framework用到了哪些第三方和第三方的版本信息]
2.在TestFrameworkDemo 工程中,增加 podFile文件,在其中加入 依赖 &pod&'AFNetworking'
& 重新pod install一下 [推荐这种方式,因为,我们用到的第三方都可以使用pod管理,方便],下面就以这种方法来说明
运行,OK!!!
framework在 &
二:使用 pod 的命令 &pod lib create 来创建 使用pod的framework
采用cocoapods自带的命令,比较方便的&
&例如 &pod lib create BZLib.可以自带demo的
命令如下 &
pod lib create YohunlUtilsPod
注意:各个版本的cocoapods生成的示例工程结构什么的,会有点不一样,比如最新的带有demo的生成的lib工程就本身就是target的名字,但是之前版本target的名字是 名字_example
pod lib create 工程名 &使会让你确认4个问题,由此来建立工程,4个问题都是很简单的,你可以自行选择
注意到了没?这里我们的&YohunlUtilsPod 目录下,并没有podfile文件,那么我们建立的库要怎么依赖第三方的啊.这里就是
YohunlUtilsPod.podspec 文件出场了,在这个文件中,可以制定我们生成的framework依赖于什么.有关于spec文件,是关键文件,原则上,只要我们把这个文件交给别人,别人就可以添加我们的lib到工程里了
编辑YohunlUtilsPod.podspec 文件(此文件实际上是 ruby格式的,如果你用ruby相关的编辑器打开,就能高亮显示了),修改内容为
Pod::Spec.new do |s|
&&&&&&&&&&& = &YohunlUtilsPod&
& s.version&&&&&&&&& = &1.0.0&
& s.summary&&&&&&&&& = &测试pod生成framework的YohunlUtilsPod.&
& s.description&&&&& = &测试用的,我们用来测试使用pod
lib create 生成的framework工程&
& s.homepage &&&&&&& = &&
& # s.screenshots &&& = &&, &&
& s.license&&&&&&&&& = 'MIT'
& s.author &&&&&&&&& = { &yohunl& =& & }
& s.source &&&&&&&&& = { :git =& &&, :tag =& s.version.to_s }
& # s.social_media_url = '&TWITTER_USERNAME&'
& s.platform &&& = :ios, '7.0'
& s.requires_arc = true
& s.source_files = 'Pod/Classes/**/*'
& s.resource_bundles = {
&&& 'YohunlUtilsPod' =& ['Pod/Assets/*.png']
& # s.public_header_files = 'Pod/Classes/**/*.h'
& # s.frameworks = 'UIKit', 'MapKit'
&& s.dependency 'AFNetworking'
验证podspec文件是否正确是使用命令 &在podspec所在目录下执行 &pod&lib&lint
如果提示错误的话,它会给出详细的提示,你照着修改就好了,备注:我已经将源码上传到了github上(你也可以上传你的私有git服务器,一般公司都应该有自己的git服务器)
更改完后,在工程中再加入 &YONetwork.h和.YONetwork.m&
再运行 pod install &
SZ-lingdaiping:Example yohunl$ pod install
Updating local specs repositories
Analyzing dependencies
Fetching podspec for `YohunlUtilsPod` from `../`
[!] Unable to satisfy the following requirements:
- `YohunlUtilsPod (from `../`)` required by `Podfile`
- `YohunlUtilsPod (from `../`)` required by `Podfile`
- `YohunlUtilsPod (= 0.1.0)` required by `Podfile.lock`
那么删掉 &Podfile.lock文件,因为我们更改了podspec文件里的库的版本号了
看到没,是在 Development Pods文件夹下,因为并没有上传到官方去,所以,在此处是 私有的,所以在Development Pods文件夹下 &.
接下来,如同第一个一样,添加一个新的target,添加 run script脚本 ,运行它,得到 &
建立一个测试工程
注意上面图里面的文字,此处因为我们的framework工程采用dynamic 模式的(上文有论述!!!) &所以需要在Embedded Binaries下添加相应的库.至于为什么还要添加&AFNetworking.framework,上面也有论述,是因为我们打包的.framework并没有包含AFNetworking.framework,如果不加上,运行起来,还是要报错的哦
好了,第一部分讲完了
那么我们怎么使用 像我们使用其它开源库那样的,只要在demo工程里添加一句
pod ‘YohunlUtilsPod' 然后pod install一下就可以添加呢?(当然了,这种方式,我们一般是直接源码模式的framework加入demo工程)
这就是第二部分要讲的.
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:265875次
积分:2680
积分:2680
排名:第10423名
原创:42篇
转载:13篇
评论:67条
(2)(1)(2)(1)(1)(4)(1)(1)(1)(1)(3)(1)(1)(3)(2)(1)(1)(1)(4)(1)(1)(1)(6)(1)(2)(2)(1)(2)(1)(1)(2)(2)(2)

我要回帖

更多关于 pod framework 红色 的文章

 

随机推荐