代码管理| 手把手教你封装自己的静态库SDK

.framework是什么?

 在我们的日常开发中,经常会用到各种已经封装好的库,比如支付宝、微信SDK等等中的库,这些库可以给我们的开发带来很大的便利。
有的时候,由于工作的需要,我们需要对自己的项目进行封装,生成库,方便别人的使用。

  那什么是“库”呢?
“库”是共享程序代码的一种方式!同行总结的这句话很简单也很好的说明了它的作用!
一般的分为“静态库”和“动态库”。

“静态库”和“动态库”有什么区别?

  • “静态库” 链接时候完整的拷贝至可执行文件中,被多次使用就会有多次拷贝。
  • “动态库” 链接时候不复制,程序运行时由系统动态加载到内存,供程序调用,系统只加载一次,多个程序共用,节省内存!

iOS里静态和动态库形式

静态库形式: .a和.framework
动态库形式: .dylib和.framework

.a与.framework有什么区别

.a是一个纯二进制文件,.framework中除了有二进制文件之外还有资源文件。
.a文件不能直接使用,至少要有.h文件配合,.framework文件可以直接使用。
.a + .h + sourceFile = .framework。
 所以我们建议用.framework.

下面我们通过实际的例子自己制作一下

如图新建一个工程,创建一个JWJCreatViewHelper类。

JWJCreatViewHelper中的方法:

#import <UIKit/UIKit.h>
@interface JWJCreatViewHelper : UIView
+ (UILabel *)creatNewLabel;
+ (UIImageView *)creatNewImageView;
@end

这里重点说下,怎样饮用Bundle中的图片资源。这里使用的是简写:@"JWJFramework.bundle/open"其中JWJFramework.bundle是Bundle的名称。

+ (UIImageView *)creatNewImageView;{
    UIImageView *imageV  =[[UIImageView alloc] initWithFrame:CGRectMake(10,200,100,100)];
    imageV.image = [UIImage  imageNamed:@"JWJFramework.bundle/open"];
    imageV.backgroundColor = [UIColor clearColor];
    return imageV;
}    

如果新建一个资源包 Bundle???

  • 新建一个文件夹。
  • 把所需要的图片文件都放到该文件夹里面。
  • 重命名该文件夹,并且强制加上后缀: .bundle,这样就是一个可用的bundle文件了,再使用的时候再拖到目标工程中即可。

接下来对我们的这个.framework静态库进行一些简单的设置,如下图所示:

Build Settings下:

1、Enable Bitcode 设置为 No 2、Build Active Architecture Only 设置为 No 3、Dead Code Stripping设置为NO。 4、然后将Link With Standard Libraries设置为 NO。 5、最后将Mach-O Type设为Static Library,framework可以是动态库也可以是静态库,对于系统的framework是动态库,而用户制作的framework只能是静态库。

接下里就是设置我们有那些头文件是需要公开的,如下图设置:

自定义Framework出现 在#include< x/x.h >出现:Could not build module ‘x’的错误提示,并且在Framework的工程中有提示找不到头文件 原因是没有把对外部公开的类中,在.h引用到的类,放到pulbic里面

还要记得把要公开的类添加到我们的JWJFramework.h中:

#import <UIKit/UIKit.h>
//! Project version number for JWJFramework.
FOUNDATION_EXPORT double JWJFrameworkVersionNumber;

//! Project version string for JWJFramework.
FOUNDATION_EXPORT const unsigned char JWJFrameworkVersionString[];

// In this header, you should import all the public headers of your framework using statements like #import <JWJFramework/PublicHeader.h>
#import <JWJFramework/JWJCreatViewHelper.h>

最后要做的就是打包制作我们这个FrameWork了:

选择真机后
 Command+k 清理工程     
 Command+B 打包出真机架构下的FrameWork:
 选择任意款模拟器后
 Command+k 清理工程     
 Command+B 打包出真机架构下的FrameWork:

这个时候你就会看到FrameWork项目里的Products文件多了我们的.framework文件。

你Show in Finder一下后如果文件夹的选择状态在A位置,需要手动切换到B位置这样就可以看到下面这样的两个文件夹了,一个就是真机一个就是模拟机的:每个文件夹下都有一个JWJframework.framework文件。

接下来就是生成我们.framework文件的最后一步了:利用终端把模拟机和真机的文件我们合并成一份:

image.png

请注意:我们需要的是真机和模拟器文件下JWJframework.framework文件中的JWJframework文件。

打开终端输入:

lipo -create /Users/iOS002/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphoneos/JWJFramework.framework/JWJFramework /Users/iOS002/Library/Developer/Xcode/DerivedData/Build/Products/Debug-iphonesimulator/JWJFramework.framework/JWJFramework -output /Users/iOS002/Desktop/aaa/JWJFramework

大约是这样的:在终端中输入命令:lipo -create 模拟机和真机的FrameWorkTest文件路径(直接拉到终端就会显示)-output 一个输出路径

这里要注意,我是保存到桌面的 aaa文件中一个JWJFramework,这个不是最终的framework文件,而是其中的一部分。

生成合并后的最终的 framwork

选择模拟器文件夹下的/ 真机文件夹下的 framework文件,删除其中的 JWJFramework文件,把桌面aaa文件中的JWJFramework拉进来,这个组合后的新的framework就是终极版的 framework了。

自定义SDK的应用

- (void)viewDidLoad {
    [super viewDidLoad];
    
    UILabel *label = [JWJCreatViewHelper creatNewLabel];
    UIImageView *imageView = [JWJCreatViewHelper creatNewImageView];
    
    [self.view addSubview:label];
    [self.view addSubview:imageView];
    
}

关于检查framwork支持的架构

在编译时选择的目标设备不同的情况下编译出来framework体系结构不同,选择真机进行编辑时会
编译产生armv7、armv7s、arm64下的库文件,而选择模拟器会产生i386、x86_64下的库文件。 具体查看的方法可以执行下列命令:

lipo -info /Debug-iphoneos/Someframework.framwork/Someframework
# Architectures in the fat file: Someframework are: armv7 armv7s arm64 

lipo -info /Debug-iphonesimulator/Someframework.framwork/Someframework
# Architectures in the fat file: Someframework are: i386 x86_64 

合并后:

目前ios的指令集有以下几种:

armv6
   -  iPhone
   -  iPhone2
   -  iPhone3G
   -  第一代和第二代iPod Touch
armv7
    - iPhone4
    - iPhone4S
armv7s
    - iPhone5
    - iPhone5C
arm64
    -  iPhone5S

模拟器32位处理器测试需要i386架构, 模拟器64位处理器测试需要x86_64架构, 真机32位处理器需要armv7,或者armv7s架构, 真机64位处理器需要arm64架构。

所有,只有最终合成的SDK支持 arm64和 x86_64架构基本即可运行在模拟器和真机器上了。

最后需要补充的是:

1、在制作framework或者lib的时候,如果使用了category,则使用改FMWK的程序运行时会crash,
  此时需要在该工程中 other linker flags添加两个参数 -ObjC -all_load。(这点没有亲测)

2、带有图片资源的需要把图片打包成Bundle文件,和framework一起拷贝到相应的项目中。

3、公开的类中如果引用的private的类,打包以后对外会报错,找不到那个private的类,可以把那个private的.h放到(也没亲测)

4、namespace 冲突。静态库用了某第三方库,项目也用了同样的第三方库,在编译的时候就会有 duplicate symbol 错误,
  因为有两份同样的第三方库。解决办法就是把用到的第三方库加上自定义前缀,包括类名、delegate 协议、常量名,
  尤其需要注意 Category 的方法名要修改。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Puppeteer学习

一步一步学习Vue(十)

2394
来自专栏mukekeheart的iOS之旅

iOS项目——项目开发环境搭建

  在开发项目之前,我们需要做一些准备工作,了解iOS扩展——Objective-C开发编程规范是进行开发的必备基础,学习iOS学习——Xcode9上传项目到G...

44015
来自专栏向治洪

React native开发中常见的错误

react native环境搭建请移步:react native环境搭建 这里说说react native创建完成之后,运行中出现的常见问题, 问题1: jav...

3326
来自专栏Java技术分享

基于Metronic的Bootstrap开发框架经验总结(5)--Bootstrap文件上传插件File Input的使用

Bootstrap文件上传插件File Input是一个不错的文件上传控件,但是搜索使用到的案例不多,使用的时候,也是一步一个脚印一样摸着石头过河,这个控件在界...

3659
来自专栏美丽应用

给安卓Chrome加入主页按钮

9252
来自专栏滕先生的博客

iOS 本地推送概念步骤:属性:点击通知跳到指定控制器界面快捷回复功能(iOS 8以后可用), category 属性的使用方法

3506
来自专栏企鹅号快讯

Vue2的单元测试与调试技术

测试是一个非常美妙的世界,一旦进入根本停不下来~在Java中,我们可以使用JUnit做单元测试,但在前端开发中,想做单元测试并不是一件特别容易的事情,但如果你采...

22810
来自专栏大前端开发

微信小程序从子页面退回父页面时的数据传递

我们知道,在微信小程序中,从一个页面转到另一个页面,一般情况下可以通过navigate或redirect时候的url来携带参数,然后在目标页面的onLoad函数...

1241
来自专栏java闲聊

SpringBoot+Vue2.x登陆功能

3144
来自专栏hrscy

iOS 百度地图 Demo

3.iOS 9 之后不能直接使用 HTTP 进行请求,需要在 Info.plist 新增一段用于控制 ATS 的配置:

1271

扫码关注云+社区

领取腾讯云代金券