iOS SDK封装Framework带资源文件封装

简书地址

[简书地址](https://www.jianshu.com/p/2cdaab20ea72

一、新建主项目

主项目的ProjectName是HelloFramework( SDK的主项目 )

二、创建Framework

在主项目里创建Framework,暂时命名MyFramework

Project - > Editor - > Add Larget - > Cocoa Touch Framework

1.png

三、配置Framework信息

1、Architectures 配置支持的指令集

  • Project - > Target - > MyFramework - > Build Settings
  • Architectures配置支持的指令集,增加arm64e、armv7s

如下:

2.png

备注:系统已经默认配置了 arm64、armv7

指令集 支持设备设备
armv6 iPhone、iPhone 3G、iPod 1G、iPod 2G
armv7 iPhone 3GS、iPhone 4、iPod 3G、iPod 4G、iPod 5G、iPad、iPad 2、iPad 3、iPad Mini
armv7s iPhone 5、iPhone 5C、iPad 4
arm64 iPhone 5s、iPhone 6、iPhone 6P、 iPhone 6s、 iPhone 6sP、 iPhone 7、iPhone 7P、iPad Air、Retina iPad Mini
arm64e iPhone XR、iPhone XS Max

2、Build Active Architecture Only修改为NO,否则生成的静态库就只支持当前选择设备的架构。

Build Active Architecture Only 修改为 NO

3、Mach-O Type 选择是Static Library(静态库)还是Dynamic Library(动态库默认)

Mach-O Type 设置为 Static Library(静态库)

备注:使用动态库要注意需要在 Linked Frameworks and Libraries 和 Embedded Binaries 都加入对应的动态库。

如下:

3.png

4、设置Headers Phase

步骤:Target - > MyFramework - > Build Phases - > Headers

  • Public:需要暴露出来的 h 文件
  • Private:不想公开的 h 文件
  • Project:显示你MyFramework里面的所有你创建的 h 文件
5.png

5、设置最低兼容版本

如下:

4.png

6、新建一个FrameworkManager文件

在FrameworkManager类里实现了一个方法

//.h文件声明
#import <Foundation/Foundation.h>

@interface MyFrameworkManager : NSObject

+ (UIViewController*)creatFrameworkFileViewController;

@end
//.m文件实现
#import "MyFrameworkManager.h"
#import "FrameworkFileViewController.h"

@implementation MyFrameworkManager

+ (UIViewController*)creatFrameworkFileViewController{
    FrameworkFileViewController *vc = [[FrameworkFileViewController alloc] initWithNibName:GetNibName(@"FrameworkFileViewController") bundle:[NSBundle mainBundle]];
    
    NSLog(@"subviews:%@",vc.view.subviews);
    return vc;
}
@end

7、引入头文件

默认生成的.h文件中,我的是MyFramework.h,把所有需要暴露的.h文件都用#import 引入,记住一定要将所有需要暴露的.h文件都引入,也就是上面Headers-Public中加的所有.h文件,不然编译后生成的.framework在引用的时候会有警告。
如下:

4.png

8、回到主项目,引用MyFrameworkManager

/// 引入头文件
#import <MyFramework/MyFramework.h>

// 主项目当中
UIViewController *vc = [MyFrameworkManager creatFrameworkFileViewController];

9、生成Framework包

打包Framework:分为真机和模拟器,这两个生成的framework是不一样的。(如果说你需要生成一个既可以真机使用又可以模拟器使用的,那就分别生成,最后在合并在一起)。按照下图将编译的 Device 选择为真机 ,然后按下 Command + B 开始编译,编译成功后右键 Products 文件夹下的 .framework 文件,点击 Show in Finder。

四、xib文件和图片的存放和引用

友情提示:资源文件都放在Bundle文件当中,如果放在Framework文件当中,后面打包上传的时候会出现Found an unexpected Mach-O header code: 0x72613c21

创建bundle,放置资源文件(nib文件,图片)

1、新建一个bundle文件,这里暂时命名为KJFramework.bundle

如下:

6.png

2、显示包内容,将图片等资源放入bundle文件当中

如下:

7.png

第一种编译成nib文件

1、将xib文件编译成nib文件
8.png
  • 打开终端:cd 需要转换的xib目录
  • 输入编译:ibtool --errors --warnings --output-format human-readable-text --compile ibtool --errors --warnings --output-format human-readable-text --compile FrameworkFileViewController.nib FrameworkFileViewController.xib

编译完成会生成如下文件:

9.png

第二种生成nib文件

1、编译文件,Command + B 生成Framework文件
5.png
2、Show in Finder Framework文件,从中找到一个FrameworkFileViewController.nib文件

备注:一旦xib文件发生变化,就需要重新编译nib文件,然后替换

3、读取bundle资源包中的图片

把Bundle文件导入到我们的framework中,我们用到图片的时候,就取Bundle中的图片来用。

//FrameworkFileViewController.m文件实现
#import "FrameworkFileViewController.h"

@interface FrameworkFileViewController ()

@property (unsafe_unretained, nonatomic) IBOutlet UIImageView *imageView;

@end

@implementation FrameworkFileViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.imageView.image = [UIImage imageNamed:GetBundleImage(@"tiaotiaosu")];
}

- (IBAction)changeImage:(UIButton *)sender {
    if (_imageView.highlighted) {
        self.imageView.image = [UIImage imageNamed:GetBundleImage(@"jienigui")];
    }else{
        self.imageView.highlightedImage = [UIImage imageNamed:GetBundleImage(@"kabisou")];
    }
    self.imageView.highlighted = !self.imageView.highlighted;
}

- (IBAction)dismiss:(UIButton *)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}
@end

五、引入第三方库

1、pod时候选择Framework文件

3.png

2、使用Framework文件的时候,同样需要引入所需的第三方库

六、Framework 的导出与文档

1、切换到 Release 模式

Product --> Edit Scheme --> Build Configuration

6.png

2、导出 Framework

(1)在 Target 为 MyFramework 下,选择模拟器和Generic iOS Device各自 Command + B 一次
(2)在工程目录 Products 下 -> 右击 Framework -> Show in Finder,会看到有两个文件夹,一个是真机包,一个是模拟器包。
  • 真机包:Release-iphoneos
  • 模拟机包:Release-iphonesimulator

查看包所支持框架:lipo -info 路径/MyFramework.framework/MyFramework

1.png

armv7 arm64 armv7s arm64e 说明是真机

i386 x86_64 说明是模拟机

(3)将合成的MyFramework 包替换其中的一个,然后这个 MyFramework.framework就是我们需要

合并:lipo -create 真机路径/MyFramework.framework/MyFramework 模拟器路径/MyFramework.framework/MyFramework -output 真机路径/MyFramework.framework/MyFramework

再次查看包支持框架:二者均在,说明合并成功

2.png

友情提示:实践证明弄模拟机的i386、x86_64没有什么用处,而且后面上传时候还会报错,让你剔除这两框架。

七、Bug总结

1、error: Invalid bitcode signature

clang: error: linker command failed with exit code 1 (use -v to see invocation)

1.png
  • 原因:Deployment Target 版本低于Framework要求的最低版本
  • 解决方案:修改 Deployment Target 版本

2、Could not load NIB in bundle

2.png
  • 原因:加载NIB时候未找到文件
  • 解决方案:
    Targets -> Build Phases -> Link Binary With Libraries、Copy Bundle Resources 处都加上引入的Framework文件
1.png

3、ld: symbol(s) not found for architecture x86_64

  • 原因:Framework文件框架当中缺少x86_64,也就是模拟机框架
  • 解决方案:本人出现原因是因为,我只合成了真机的Framework文件,所以在模拟机跑的时候报缺少框架,但是在真机上可以正常运行。
  • 生成模拟机Framework文件和真机Framework文件,然后将两个文件合成。

4、ld: symbol(s) not found for architecture x86_64

clang: error: linker command failed with exit code 1 (use -v to see invocation)


2.png
  • 原因:未引入所需的三方库
  • 解决方案:pod 需要的三方库
    从图可以看出缺少 MJRefresh 和 CHTCollectionViewWaterfallLayout

5、All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture armv7

工程中引入的第三方静态库真机调试没有问题,打包的时候报错


1.png
  • 原因:第三方库不兼容 XCode7later 之后默认开启 BitCode
  • 解决方案:
  • 第一种:更新Framework文件使包含 Bitcode(armv7)。
  • 第二种:选择工程,在 Build Settings 中,把 ENABLE_BITCODE 设置为NO


    2.png

6、Found an unexpected Mach-O header code: 0x72613c21

打好包之后上传时候出现错误!!!

  • 第一种原因:Framework是一个Static Library,我把他添加在Embedded Binaries里面了。

  • 解决方案:

  • 第一种:从 Embedded Binaries(动态库里来文件)中删除静态Framework文件(KJFramework.framework)但是你直接删除会发现下面 Linked Frameworks and Libraries(签署了框架和库)中 Framework 文件也没了。这是需要重新往 Linked Frameworks and Libraries 里添加刚刚被删除的Framework文件。

  • 第二种:重新将Framework文件封装成Dynamic Library(动态库),使用动态库要注意需要在 Linked Frameworks and Libraries 和 Embedded Binaries 都加入对应的动态库。


  • 第二种原因:把Framework文件添加到了 Copy Bundle Resources当中
  • 解决方案:从 Copy Bundle Resources 中将Framework文件删除,这是你可能会出现,加载不出来你封装在Framework文件当中的资源文件,因此你需要把资源文件单独提炼出来用 Bundle 来装。

7、dyld: Library not loaded: @rpath/KJFramework.framework/KJFramework

4.png
  • 原因:
  • 解决方案:此处加上Framework文件即可


    2.png

8、"Unsupported Architectures. The executable for yht.temp_caseinsensitive_rename.app/Frameworks/VideoCore.framework contains unsupported architectures '[x86_64, i386]'."

55.png
  • 原因:说明自建的这个SDK里面包含了x86_64、i386 架构,当然这个AppStore是不允许的
  • 解决方案:剔除掉x86_64, i386这两个架构
  • TARGETS -> Build Phases -> 点击加号选择 New Run Script Phase -> 然后复制粘贴下面代码


    6.png
    APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"  
      
    # This script loops through the frameworks embedded in the application and  
    # removes unused architectures.  
    find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK  
    do  
    FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)  
    FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"  
    echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"  
      
    EXTRACTED_ARCHS=()  
      
    for ARCH in $ARCHS  
    do  
    echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"  
    lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"  
    EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")  
    done  
      
    echo "Merging extracted architectures: ${ARCHS}"  
    lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"  
    rm "${EXTRACTED_ARCHS[@]}"  
      
    echo "Replacing original executable with thinned version"  
    rm "$FRAMEWORK_EXECUTABLE_PATH"  
    mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"  
      
    done  
2.png
3.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容