簡書地址
[簡書地址](http://www.reibang.com/p/2cdaab20ea72)
一、新建主項目
主項目的ProjectName是HelloFramework( SDK的主項目 )
二浩习、創(chuàng)建Framework
在主項目里創(chuàng)建Framework谱秽,暫時命名MyFramework
Project - > Editor - > Add Larget - > Cocoa Touch Framework
三峡碉、配置Framework信息
1鲫寄、Architectures 配置支持的指令集
- Project - > Target - > MyFramework - > Build Settings
- Architectures配置支持的指令集,增加arm64e地来、armv7s
如下:
備注:系統(tǒng)已經默認配置了 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角撞,否則生成的靜態(tài)庫就只支持當前選擇設備的架構呛伴。
Build Active Architecture Only 修改為 NO
3、Mach-O Type 選擇是Static Library(靜態(tài)庫)還是Dynamic Library(動態(tài)庫默認)
Mach-O Type 設置為 Static Library(靜態(tài)庫)
備注:使用動態(tài)庫要注意需要在 Linked Frameworks and Libraries 和 Embedded Binaries 都加入對應的動態(tài)庫谒所。
如下:
4热康、設置Headers Phase
步驟:Target - > MyFramework - > Build Phases - > Headers
- Public:需要暴露出來的 h 文件
- Private:不想公開的 h 文件
- Project:顯示你MyFramework里面的所有你創(chuàng)建的 h 文件
5、設置最低兼容版本
如下:
6劣领、新建一個FrameworkManager文件
在FrameworkManager類里實現(xiàn)了一個方法
//.h文件聲明
#import <Foundation/Foundation.h>
@interface MyFrameworkManager : NSObject
+ (UIViewController*)creatFrameworkFileViewController;
@end
//.m文件實現(xiàn)
#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在引用的時候會有警告惊暴。
如下:
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文件當中评腺,后面打包上傳的時候會出現(xiàn)Found an unexpected Mach-O header code: 0x72613c21
創(chuàng)建bundle帘瞭,放置資源文件(nib文件,圖片)
1蒿讥、新建一個bundle文件蝶念,這里暫時命名為KJFramework.bundle
如下:
2、顯示包內容芋绸,將圖片等資源放入bundle文件當中
如下:
第一種編譯成nib文件
1媒殉、將xib文件編譯成nib文件
- 打開終端:cd 需要轉換的xib目錄
- 輸入編譯:ibtool --errors --warnings --output-format human-readable-text --compile ibtool --errors --warnings --output-format human-readable-text --compile FrameworkFileViewController.nib FrameworkFileViewController.xib
編譯完成會生成如下文件:
第二種生成nib文件
1、編譯文件摔敛,Command + B 生成Framework文件
2廷蓉、Show in Finder Framework文件,從中找到一個FrameworkFileViewController.nib文件
備注:一旦xib文件發(fā)生變化马昙,就需要重新編譯nib文件桃犬,然后替換
3、讀取bundle資源包中的圖片
把Bundle文件導入到我們的framework中行楞,我們用到圖片的時候攒暇,就取Bundle中的圖片來用。
//FrameworkFileViewController.m文件實現(xiàn)
#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文件
2、使用Framework文件的時候证杭,同樣需要引入所需的第三方庫
六田度、Framework 的導出與文檔
1、切換到 Release 模式
Product --> Edit Scheme --> Build Configuration
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
armv7 arm64 armv7s arm64e 說明是真機
i386 x86_64 說明是模擬機
(3)將合成的MyFramework 包替換其中的一個,然后這個 MyFramework.framework就是我們需要
合并:lipo -create 真機路徑/MyFramework.framework/MyFramework 模擬器路徑/MyFramework.framework/MyFramework -output 真機路徑/MyFramework.framework/MyFramework
再次查看包支持框架:二者均在揭保,說明合并成功
友情提示:實踐證明弄模擬機的i386肥橙、x86_64沒有什么用處,而且后面上傳時候還會報錯秸侣,讓你剔除這兩框架存筏。
七、Bug總結
1味榛、error: Invalid bitcode signature
clang: error: linker command failed with exit code 1 (use -v to see invocation)
- 原因:Deployment Target 版本低于Framework要求的最低版本
- 解決方案:修改 Deployment Target 版本
2椭坚、Could not load NIB in bundle
- 原因:加載NIB時候未找到文件
- 解決方案:
Targets -> Build Phases -> Link Binary With Libraries、Copy Bundle Resources 處都加上引入的Framework文件
3搏色、ld: symbol(s) not found for architecture x86_64
- 原因:Framework文件框架當中缺少x86_64善茎,也就是模擬機框架
- 解決方案:本人出現(xiàn)原因是因為,我只合成了真機的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)
- 原因:未引入所需的三方庫
- 解決方案:pod 需要的三方庫
從圖可以看出缺少 MJRefresh 和 CHTCollectionViewWaterfallLayout
5膳殷、All object files and libraries for bitcode must be generated from Xcode Archive or Install build for architecture armv7
工程中引入的第三方靜態(tài)庫真機調試沒有問題操骡,打包的時候報錯
- 原因:第三方庫不兼容 XCode7later 之后默認開啟 BitCode
- 解決方案:
- 第一種:更新Framework文件使包含 Bitcode(armv7)。
-
第二種:選擇工程赚窃,在 Build Settings 中册招,把 ENABLE_BITCODE 設置為NO
2.png
6、Found an unexpected Mach-O header code: 0x72613c21
打好包之后上傳時候出現(xiàn)錯誤?颊ァ?缦浮鹦倚!
- 第一種原因:Framework是一個Static Library河质,我把他添加在Embedded Binaries里面了。
解決方案:
第一種:從 Embedded Binaries(動態(tài)庫里來文件)中刪除靜態(tài)Framework文件(KJFramework.framework)但是你直接刪除會發(fā)現(xiàn)下面 Linked Frameworks and Libraries(簽署了框架和庫)中 Framework 文件也沒了震叙。這是需要重新往 Linked Frameworks and Libraries 里添加剛剛被刪除的Framework文件掀鹅。
第二種:重新將Framework文件封裝成Dynamic Library(動態(tài)庫),使用動態(tài)庫要注意需要在 Linked Frameworks and Libraries 和 Embedded Binaries 都加入對應的動態(tài)庫媒楼。
- 第二種原因:把Framework文件添加到了 Copy Bundle Resources當中
- 解決方案:從 Copy Bundle Resources 中將Framework文件刪除乐尊,這是你可能會出現(xiàn),加載不出來你封裝在Framework文件當中的資源文件划址,因此你需要把資源文件單獨提煉出來用 Bundle 來裝扔嵌。
7限府、dyld: Library not loaded: @rpath/KJFramework.framework/KJFramework
- 原因:
-
解決方案:此處加上Framework文件即可
2.png
8、"Unsupported Architectures. The executable for yht.temp_caseinsensitive_rename.app/Frameworks/VideoCore.framework contains unsupported architectures '[x86_64, i386]'."
- 原因:說明自建的這個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