详细介绍一下如何生带有第三方、图片、plist文件,xib文件的.framework
一、制作.framework
1.首先,我们新建工程,选择Coco Touch Framework
创建工程
2.使用CocoaPods导入cordova,打开工程,可以看到我们的第三方已导入成功,接下来就要进行一些配置了。
3.我们把需要的打包的代码都放进去
4.更改参数配置:
(1)选中 Target ,选择 Build Settings ,在 Architectures 下增加 armv7s 。
(扩充知识点:Architectures : 指定工程将被编译成支持哪些指令集;支持越多,生成的指令集数据包越大。默认使用:$(ARCHS_STANDARD)即可, 它包含了 armv7/arm64 如果要支持其他的也可以手动添加
Valid Architecures:指定可能支持的指令集,其默认是:arm64 arm64e armv7 armv7s。该列表和Architectures列表的交集,将是Xcode最终生成的二进制包所支持的指令集,
比如:Architectures支持了armv7s Valid Architectures支持了: armv7/arm64/armv7s, 那么最终只支持armv7s。
如下图所示:)
(2)Build Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构。当然我们也可以在Edit Scheme -> Run将Debug改为了release那么Build Active Architecture Only使用默认
Build Active Architecture Only修改为NO
(3)在搜索栏搜索 Mach-O Type ,将 Mach-O Type修改为 Static Library(静态库)类型。(如果要使用动态库:此时Mach-O Type选择Dynamic Library即可)
将 Mach-O Type修改为 Static Library
(4)选中 Target ,选择 Build Phases - Headers ,可以看出有三个选项,分别是 Public 、Private 、Project ,把需要公开给别人的 .h 文件拖到 Public 中,把不想公开的,即为隐藏的 .h 文件拖到 Project 中。
选择需要公开的头文件
5.完成上述步骤之后,在默认生成的.h文件中,我的是wee.h,把所有需要暴露的.h文件都用#import 引入,记住一定要将所有需要暴露的.h文件都引入,也就是上面Headers-Public中加的所有.h文件(截图我只导入了部分,写的时候要导入完),不然编译后生成的.framework在引用的时候会有警告。
导入所有要暴露在外的头文件
6.是否支持bitcode
如果需要支持bitcode,在TAGETS的Build setting中搜索Other C Flags,添加命令“-fembed-bitcode”
7.Dead Code Stripping : YES 消除无效代码(一些老的文章说是设置为NO,看文档新版xcode还是设置为YES默认也是如此)
8.Link With Standard Libraries : YES(默认) 用标准库连接(一些老的文章说是设置为NO,当我打包动态库的时候会报错)
9.如果你用了Category可以在Other Linker Flags 添加 -ObjC 即可
10.设置支持的最低iOS系统,如下:
11.打包framework:分为真机和模拟器,真机生成framework,选择如下图,(要生成模拟器,就选择一个模拟器),然后按下 Command + B 开始编译,编译成功后右键 Products 文件夹下的 .framework 文件,点击 Show in Finder。
(如果你想生成模拟器和真机都能用的,可以参考一下连接:https://www.jianshu.com/p/3f9bbb3959b5)
生成真机.framework
12.测试打包完成的.framework,把生成的.framework导入测试demo中,(注意:如果你framework使用了cocoapods导入第三方,那么我们demo也需要使用cocoapods导入第三方,不然会报错!使用我们自己制作的framework时要导入头文件 #import ),然后 Command + B 开始编译,如果没报错,恭喜你完成了第三方的导入。下面看看带有plist文件和图片的framework
二、制作bundle
方法1:使用xcode制作。
具体制作方法可以自己百度看看,也可以看下面的连接:https://www.jianshu.com/p/58c3a27b2649
方法2:把图片放到一个文件夹下,然后压缩这个文件夹,修改后缀名.zip为.bundle。
bundle的使用:
1.把Bundle文件导入到我们的framework中,我们用到图片的时候,就取Bundle中的图片来用。使用时注意,具体用法
读取bundle资源包重的图片
2.command + B,把新生成的framework重新导入demo中,并把Bundle也导入demo,运行demo。(注意:如果demo中不导入Bundle,图片是不会显示出来的)。(我使用的xcode11,command + B,生成的framework里面是包含Bundle文件的,可能不需要再把Bundle导入demo了。有兴趣的小伙伴,你们可以试试)
如果没有把Bundle导入demo,图片没有显示,可以用下面的方法加载图片,然后在我们的·demo中的Copy Bundle Resources中添加这个framework(红字不懂得可以看下面xib的这步操作)。
重新导入framework和Bundle运行程序
如果图片可以显示出来,说明我们的Bundle制作成功了,图片的问题我们解决了,下面要解决plist文件了。其实根据我们Bundle的制作过程,不难想到plist文件的使用原理。
三、plist文件的使用
1.其实plist文件的使用原理和图片一样,只不过图片需要制作Bundle,而plist文件不需要。把plist文件拖进framework中,重新编译framework,把重新编译的framework和plist文件都拖到demo中,(也可以按照图片的方法,不把.plist 文件放到demo中的试试看,如果这么做的话,使用plist文件的路径可能要改下,然后在我们的·demo中的Copy Bundle Resources中添加这个framework(红字不懂得可以看下面xib的这步操作)。)
plist拖进framework中
plist的使用如下:
四、xib
如果你要打包的framework中包含xib,我们在初始化xib时要这样写,带上你framework的名字。然后在我们的·demo中的Copy Bundle Resources中添加这个framework。
xib的使用方法
初始化写法
导入framework
如果以上完成后运行没有报错,恭喜你framework制作成功并可以使用了,
我看了一篇文章他报了这个错误:(如果没有请忽略)
以下是他的解决方法:
错误原因很好理解就是说在nib里找不到图片,我觉得这肯定是一个低级错误,是路径的配置问题,所以就把问题定位到初始化nib文件:
单单从代码看找不出问题,单经过尝试后一下方法是可以的:
二、如果是打包动态framwork
如果Mach-o Type选择的是Dynamic Library动态库,即我们创建的是动态framwork:
直接把xib文件放入到framwork工程中即可,然后编译生成framework,把framework放入到目标工程中
使用动态库要注意:需要在Linked Frameworks and Libraries和Embedded Binaries都加入对应的动态库.
(在xcode11中,Embedded Binaries变成了如下格式,添加framework,然后选择embed&sign,就可以了,这时候就可以看到Build Phases下新增了一个embed framework)
代码使用:
//加载方式1
NSBundle *SDKBundle = [NSBundle bundleForClass:[NewViewController class]];
//加载方式2 bundleWithIdentifier是Framework的BundleIdentifier
NSBundle *SDKBundle = [NSBundle bundleWithIdentifier:@"com.wecan.Framework-Xib"];
NewViewController *vc = [[NewViewController alloc] initWithNibName:@"NewViewController" bundle:SDKBundle];
[self presentViewController: vc animated:YES completion:nil];
注意⚠:
1. -ObjC:加了这个参数后,链接器就会把静态库中所有的 Objective-C 类和分类都加载到最后的可执行文件中。
2. -all_load:会让链接器把所有找到的目标文件都加载到可执行文件中,但是千万不要随便使用这个参数!假如你使用了不止一个静态库文件,然后又使用了这个参数,那么你很有可能会遇到 ld: duplicate symbol 错误,因为不同的库文件里面可能会有相同的目标文件,所以建议在遇到 -ObjC 失效的情况下使用 -force_load 参数。
3. -force_load:所做的事情跟 -all_load 其实是一样的,但是 -force_load 需要指定要进行全部加载的库文件的路径,这样的话,你就只是完全加载了一个库文件,不影响其余库文件的按需加载。
注意3图
出现错误!
今天在引入一个静态framework库时候,编译遇到了“Can't map file, errno=22 file 'xxx' for architecture arm64(armv7)”问题!
起因是我在主项目中,build setting-----》other linker flags 中-force_load了该framework库
1,找到引用项目的build setting----》build active architecture only ----》设置成NO
我原本就是no,所以结果没啥用
2,最后尝试了这一种办法
将主项目中other linker flages 中的-force_load "XXX.framework"改成“-force_load "XXX.framework/XXX”其中XXX是静态库名。
参考连接:https://www.cnblogs.com/yk123/p/9340268.html
https://www.jianshu.com/p/3f9bbb3959b5
https://www.jianshu.com/p/5ef5e21d887c
https://www.cnblogs.com/oc-bowen/p/7478461.html
https://www.jianshu.com/p/8727da2d5cb5
https://www.jianshu.com/p/06bdbc7fd4bd
https://www.jianshu.com/p/3f9bbb3959b5