打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
iOS 制作兼容64位iOS系统的Framework包

最近在要把写的代码打包成Framework包给其他人用,照着网上的博客介绍的过程做出来以后,发现在64位上运行时会崩溃掉,数个小时的google和测试后,最终在github上找到了一位大神写的文章,他自己写了一个脚本,将该问题解决掉了。(32个赞!)


下面是对他文章的翻译,注释是我在制作的工程中发现要注意的地方,原文地址:https://github.com/csexton/ios-framework-builder/blob/master/HOWTO.md


我的灵感极大程度上来自于Jeff VerKoeyen的iOS Framework指南,然而当苹果发布了新的64位架构后,打破了原有的一些事情。主要是我们现在有32位和64位的模拟器架构。不幸地是xcode并没有给你任何的方式来指定你想给模拟器设置的架构,当我在模拟器里编译时,我无法弄清楚如何巧妙地编译一个臃肿的二进制包。我可以用xcodebuild和一些环境变量来解决这个问题。我还希望把所有的框架编译工作放在一起,而不是对不同的target进行不同的编译设置。


在这篇文章的末尾,你将得到一个单独的aggregate target,它会构建你的二进制包,并把它编译成.framework。原始的target通常只是构建了一个.a文件。


1 制作一个通用的Cocoa Touch Static Library

1.1 创建一个新的工程

如果有必要,那就创建一个新的library工程。

这只会生成一个.a二进制包和hearders文件。我们将添加一个target,这个target将把它转换成一个合适的framework


1.2 Framework Header

你需要创建一个这个framework总的要导入的头文件。这个会提供给你的library的使用者,而不是这个library的本身。

例如我已经有一个叫作"MyFramework"的framework包,还有一个MyFramework/MyFramework头,像下面这样:

  1. #import <Foundation/Foundation.h>  
  2. #import <MyFramework/MyFramework.h>  

我只要将该头文件添加到工程中即可使用MyFramework包中的功能了。

1.3 公开的文件

首先你需要添加一个Copy Header build phase。到状态栏,然后点击:

  • Editor
  • Add Build Phase
  • Add Copy Headers Build Phase
(注:不知道为什么我这里上面的那一项是不可用的,不过选中target后,在Build Phases中下面搜索框前面的+也是可以的,如下图)

这时你看的界面如下所示:


为了暴露你插件包中的功能,你需要公开对外可见的头文件。用XCode的"Target Membership"来完成。

为了设置membership mash ?-?-0,然后勾选或不勾选Target Membership,然后设置为"project"


注:当你要把一个头文件放到.framework里时,你就要这样做。

(注:在我测试的过程中发现,要把那一项设置为public的才行,是project的话对外还是不可见的)

更新公开头文件的路径。在build setting中搜索"Public Headers Folder Path",然后将其值改变为:

  1. $(PROJECT_NAME)Headers  


(注:这一项一定要设置,否则头文件里任何一个.h文件都没有)
这会把头文件放到一个像MyProjectHeader中的文件夹中,它会被复制到framework包中。

1.4 禁用Code Striping

点击工程名,build settings,选择"combined",然后更新下面的设置:

  • Dead Code Stripping: No
  • Strip Debug Symbols During Copy: No
  • Strip Style: Non-Global Symbols

2 Framework Target

创建一个新的aggregate target

从菜单栏中添加一个新的target:

  • File
  • New
  • Target
  •         Other
  •         Aggregate

像Jeff一样,我喜欢称它为"Framework"

Add Dependencies

现在点击project,然后编辑"Build Settings",在这里你可以把你的library当作framework的一个依赖项。

现在你会看到它列在了你的工程下面:

构建Framework

现在添加build phase,它将运行脚本来完成编译和文件创建。
在菜单栏上选择:
  • Editor
  • Add Build Phase
  • Add Run Script Build Phase
现在你有两个选择,你可以粘贴脚本内容到XCode工程设置中,或者只是使用它调用你的脚本。我更喜欢后者,因为git可以追踪并整合你的编译脚本就像正常的代码一样。


只要粘贴一个命令到你的脚本中,如果有必要再调整路径。

  1. set -e  
  2. ${PROJECT_DIR}/${PROJECT_NAME}/Scripts/framework-builder  

这是真正神奇的地方,这个脚本处理了所有关键的事情。把脚本内容放到一个叫Scripts/framework-builder的文件中,然后添加到工程中。

关于这个脚本有几点要解释一下:

  • 我使用的ruby,很大程度是因为它在bash中处理的大量复杂的边界情况。然后这可以使用包括中Mac OS X系统中的ruby命令,根本无需依赖包。它应该会起作用。他设置避免了任何可能被安装的ruby版本的管理。
  • 这会重新编译所有target来确保满足所有包括进来的架构。这是一个有点笨拙的解决方案,但是却很管用。
  • 假定$PROJECT\_NAME与你的library和framework的名字一样。如果不是就编辑一下这个脚本。
从github standalone/framework-builder上可以下载这个脚本,或者执行如下命令:
  1. curl https://raw.github.com/csexton/ios-framework-builder/master/standalone/framework-builder > Scripts/framework-builder  

如果你对这个处理过程有任何更改,请随意发送pull request,我相信苹果会有一天对其进行改善的。

(注:编译成功之后,那生成的framework包在哪里呢?右击XCode左边的Products组下面的.a文件,然后在Finder中显示,打开以后并没有framework包,它实际上在这个文件夹的上一层,好了,复制好路径,到前往中把它找到吧!)

============翻译完毕,如果有任何不对的地方希望留言指出^_^======================

制作资源Bundle包


写到这还没有结束,因为在我制作的framework包中用到了xib、图片这些资源,这些东西是不能一起放到刚才制作的framework包里的,所以还要把他们一起打包出来一个bundle包,在使用时这个bundle包和framework包一起使用。好了,现在说一下这个bundle包的制作过程吧!

1. 再添加一个target,然后选择Bundle那项,如下:



命名为:Resource。这时在Xcode的左边多了下个组,如下:



为了使我们生成的Resource.bundle里只有需要的资源文件,没有其他的多余项,上面的那些可以完全删除掉。

2. 在Targes中选中Resource,到Build Settings中将Base SDK改为Latest iOS(iOS版本)

3. 还是在Build Settings中到Packaging下将Info.plist File后面的值删掉,否则编译的时候会报找不到.plist文件(因为刚刚到删掉掉了- -)

4. 在Build Phases中将涉及到的xib和图片都放到Copy Bundle Resources中。

5. 再选择Targest的Framework,在Target Dependencies中添加Resouce.bundle,这样在编译Framework时,这个bundle包也会一起被编译的。

6. 现在编译还会出错,之前引用到的图片都多了一层目录,所以所有用的地方都要改一下,例如如下:
  1. NSBundle *bundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"MyFrameworkResources" withExtension:@"bundle"]];  
  2.     MyViewController *controller = [[MyViewController alloc]initWithNibName:@"MyViewController" bundle:bundle];  

但是请注意:在IB中对xib上的控件设置的图片并不会收到影响,不用加上这一层路径

7. 选择Framework,然后编译,经过我的测试,选择是模拟器还是Device都是一样的。

8. 找到Framework包和bundle包,一起交给别用去用吧^_^。

有几点要注意的:
  • Resource.bundle一定要放在使用这个资源包的工程下面,否则会找不到资源文件。
  • 我刚才说的是把写好的代码,打包出来一个framework包和bundle包,你在做时最好是直接建一个cocoa touch static library工程,然后再建一个测试的工程,以免文件过多时再打包不好弄。在测试工程中可以直接引用生成的framework,这样在编译完framework后就不用再替换一次测试工程中的framework包了。
  • 如果在framework中用到了category,那么在使用该framework包时要在工程的Build Settings中Linking下的Other Linker Flags设置为-all_load。
  • 尽量在源代码所在的那个目录中只放.m和.h文件,因为这个目录中的所有文件都会被放到framework包中,这样徒增了framework包的大小。
  • 在新建完Cocoa Touch Static Library后,你会发现在Frameworks的组下面少了UIKit.framework,如果你用到了这里面的东西,那在Build Phases中将其添加进来就好。



在这篇文章中作者写的两个category,一个是对NSBundle,一个是对UIImage,用起来很方便:

  1. @interface NSBundle (MyLibrary)  
  2. + (NSBundle*)myLibraryResourcesBundle;  
  3. @end  
  4.   
  5. @implementation NSBundle (MyLibrary)  
  6.   
  7. + (NSBundle*)myLibraryResourcesBundle {  
  8.     static dispatch_once_t onceToken;  
  9.     static NSBundle *myLibraryResourcesBundle = nil;  
  10.     dispatch_once(&onceToken, ^{  
  11.         myLibraryResourcesBundle = [NSBundle bundleWithURL:[[NSBundle mainBundle] URLForResource:@"MyLibraryResources" withExtension:@"bundle"]];  
  12.     });  
  13.     return myLibraryResourcesBundle;  
  14. }  
  15.   
  16. @end  

  1. @implementation UIImage (MyLibrary)  
  2. + (UIImage*)myLibraryImageNamed:(NSString*)name;  
  3. @end  
  4.   
  5. @implementation UIImage (MyLibrary)  
  6.   
  7. + (UIImage*)myLibraryImageNamed:(NSString*)name {  
  8.     UIImage *imageFromMainBundle = [UIImage imageNamed:name];  
  9.     if (imageFromMainBundle) {  
  10.         return imageFromMainBundle;  
  11.     }  
  12.   
  13.     UIImage *imageFromMyLibraryBundle = [UIImage imageWithContentsOfFile:[[[NSBundle myLibraryResourcesBundle] resourcePath] stringByAppendingPathComponent:name]];  
  14.     return imageFromMyLibraryBundle;  
  15. }  
  16.   
  17. @end  


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
iOS开发——创建你自己的Framework
iOS使用Workspace来管理多项目
android支持第三方jar包,以及Eclipse如何导入jar包
CocoaPods详解之----使用篇
Eclipse 安装Gradle插件
如何修改java工程中lib中的.jar包中的文件 -Java-技术中心-启天网
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服