iOS SDK封裝Framework帶資源文件封裝

簡書地址

[簡書地址](http://www.itdecent.cn/p/2cdaab20ea72

一、新建主項目

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

二、創(chuàng)建Framework

在主項目里創(chuàng)建Framework,暫時命名MyFramework

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

1.png

三、配置Framework信息

1、Architectures 配置支持的指令集

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

如下:

2.png

備注:系統(tǒng)已經(jīng)默認配置了 arm64、armv7

指令集 支持設(shè)備設(shè)備
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)庫就只支持當前選擇設(shè)備的架構(gòu)。

Build Active Architecture Only 修改為 NO

3、Mach-O Type 選擇是Static Library(靜態(tài)庫)還是Dynamic Library(動態(tài)庫默認)

Mach-O Type 設(shè)置為 Static Library(靜態(tài)庫)

備注:使用動態(tài)庫要注意需要在 Linked Frameworks and Libraries 和 Embedded Binaries 都加入對應(yīng)的動態(tài)庫。

如下:

3.png

4、設(shè)置Headers Phase

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

  • Public:需要暴露出來的 h 文件
  • Private:不想公開的 h 文件
  • Project:顯示你MyFramework里面的所有你創(chuàng)建的 h 文件
5.png

5、設(shè)置最低兼容版本

如下:

4.png

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在引用的時候會有警告。
如下:

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文件當中,后面打包上傳的時候會出現(xiàn)Found an unexpected Mach-O header code: 0x72613c21

創(chuàng)建bundle,放置資源文件(nib文件,圖片)

1、新建一個bundle文件,這里暫時命名為KJFramework.bundle

如下:

6.png

2、顯示包內(nèi)容,將圖片等資源放入bundle文件當中

如下:

7.png

第一種編譯成nib文件

1、將xib文件編譯成nib文件
8.png
  • 打開終端:cd 需要轉(zhuǎn)換的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文件發(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文件

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總結(jié)

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,也就是模擬機框架
  • 解決方案:本人出現(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)


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

工程中引入的第三方靜態(tài)庫真機調(diào)試沒有問題,打包的時候報錯


1.png
  • 原因:第三方庫不兼容 XCode7later 之后默認開啟 BitCode
  • 解決方案:
  • 第一種:更新Framework文件使包含 Bitcode(armv7)。
  • 第二種:選擇工程,在 Build Settings 中,把 ENABLE_BITCODE 設(shè)置為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 都加入對應(yīng)的動態(tài)庫。


  • 第二種原因:把Framework文件添加到了 Copy Bundle Resources當中
  • 解決方案:從 Copy Bundle Resources 中將Framework文件刪除,這是你可能會出現(xiàn),加載不出來你封裝在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 架構(gòu),當然這個AppStore是不允許的
  • 解決方案:剔除掉x86_64, i386這兩個架構(gòu)
  • 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
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容