創(chuàng)建framework庫之間的依賴及庫資源的加載

主要解決以下三個問題:

  1. 自己封裝的framework庫有多個公共的方法,model,類等,所以打算封裝一個公共類庫,讓其他的framework庫進行依賴;
  2. framework庫中包含圖片資源,plist文件的讀取 ;
  3. 資源文件bundle的創(chuàng)建方式;

1. 一般公共類庫的封裝

不涉及資源問題,就是一些公共方法的封裝,封裝流程和一般的framework庫沒區(qū)別,注意點:

  1. 暴露.h文件;
  2. image.png
  3. image.png
  4. 設置成release版本;
  5. 如果用了Category分類,需要在工程中other linker flags中添加-objC,如果依然有問題,再添加-all_load;
  6. 關于符號表的警告,這時需要將Generate Debug Symbols設置為NO即可關閉符號表警告;
  7. 如果需要支持bitcode:在TAGETSBuild setting中搜索Other C Flags,添加命令-fembed-bitcode。同樣的設置在PROJECT中。

2. 創(chuàng)建資源文件bundle

兩種方式

  1. 直接創(chuàng)建文件夾,拖入文件,再修改后綴為.bundle;
    此方法缺點是如果有新的資源需要導入,又得重新在創(chuàng)建文件夾,把上一次的資源全部拷貝進來,更新新的資源,很麻煩;
  2. 使用Xcode生成,具體如下:
  1. 創(chuàng)建Bundle文件:創(chuàng)建工程,選擇如下:


    image.png
  2. 進行配置:


    image.png
image.png
image.png
image.png
image.png

info.plist文件處理:(打包的bundle給別人使用,別人在打包完上傳過程中可能會極大的坑,加上如下處理)


image.png
image.png

然后把圖片導入工程,build即可;分別選擇真機和模擬器,然后各運行一遍,即可生成真機和模擬器使用的bundle;

參考鏈接:
http://www.itdecent.cn/p/d7c59c079249?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation

3. 創(chuàng)建包含資源和依賴庫的framework庫

  1. 創(chuàng)建的SDK,這里命名為 AM300QuestionSDK,選擇的是framework庫;
  2. 把上面創(chuàng)建的依賴庫 AM300PublicSDK.framework添加到AM300QuestionSDK文件夾下;
  3. 對SDK進行配置:具體配置和上面創(chuàng)建framework庫一樣;
  4. 把工程中使用到公共類庫的地方,修改成: #import <AM300PublicSDK/XXX.h>;
  5. 把創(chuàng)建好的資源: questionimages.bundle 導入到AM300QuestionSDK下;
  6. 資源文件的調用問題修改:
    因為現(xiàn)在iOS只能創(chuàng)建自己的靜態(tài)庫,靜態(tài)庫資源加載方式:
    plist文件如下:
NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Am300QuestionSDK.framework/questionimages" ofType:@"bundle"];
    NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
    NSString *plistPath = [bundle pathForResource:@"QuestionnaireList" ofType:@"plist"];

image如下:

NSString *bundlePath = [[NSBundle mainBundle] pathForResource:@"Am300QuestionSDK.framework/questionimages" ofType:@"bundle"];
    NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];
    
    
    NSString *fileName = [NSString stringWithFormat:@"%@%@",imageName,@"@2x.png"];
    NSString *filePath = [bundle pathForResource:fileName ofType:nil];
    UIImage *img = [UIImage imageWithContentsOfFile:filePath];

修改完,然后運行生成framework文件;

4. 庫的使用

  1. 創(chuàng)建一個工程,導入SDK及其依賴庫,創(chuàng)建SDK的調用類CRQuestionViewController,用于驗證SDK是否正常工作;


    image.png
  2. 現(xiàn)在運行工程,發(fā)現(xiàn)可以正常運行,但是資源文件沒有加載成功,
    因為靜態(tài)庫framework讀取資源文件需要額外創(chuàng)建一個copy Files 進行讀取
    操作如下:


    image.png
image.png

然后運行,成功.

注:不管是資源文件.bundle還是framework庫,都存在真機和模擬器,上架需要記得使用真機生成;
上面第二步一定不能少,除非你的資源文件是直接放在主工程目錄下的;不過不把資源文件放在framework庫中,那也就沒必要打framework庫了,直接用.a庫也行了,主要還是看需求;

參考鏈接:
http://www.itdecent.cn/p/c92c08d8afda
https://blog.csdn.net/ljl5125/article/details/52210283
http://www.itdecent.cn/p/fb5083f2c0d2

5.創(chuàng)建可調式工程

以上的方式,如果SDK有問題,修改很麻煩,所以可以創(chuàng)建可調試工程,運行沒問題直接生成framework庫,操作如下:

  1. 創(chuàng)建項目工程TiaoShiDemo

  2. 通過TARGETS 添加 一個我們要創(chuàng)建的SDK,這里命名為 AM300QuestionSDK,選擇的是framework庫,不創(chuàng)建.a

  3. 把我們SDK需要的類導入AM300QuestionSDK文件夾下;

  4. 把上面創(chuàng)建的依賴庫 AM300PublicSDK.framework添加到AM300QuestionSDK文件夾下;

  5. 通過TARGETS—> AM300QuestionSDK :對SDK進行配置:具體配置和上面創(chuàng)建framework庫一樣;

  6. 把工程中使用到公共類庫的地方,修改成: #import <AM300PublicSDK/XXX.h>

  7. 選擇AM300QuestionSDK,進行編譯,編譯通過后,選擇TiaoShiDemo編譯,發(fā)現(xiàn)報錯;因為我們的TiaoShiDemo工程沒有AM300PublicSDK.framework,需要添加一個;

  8. 把創(chuàng)建好的資源: questionimages.bundle 導入到AM300QuestionSDK下;

然后運行工程即可

問題:

這樣創(chuàng)建的AM300QuestionSDK,在訪問資源時,需要使用如下方式:

/得到framework路徑
#define FrameworkPath  [[NSBundle mainBundle] pathForResource:@"Frameworks/AM300QuestionSDK" ofType:@"framework"]

//得到對應的bundle路徑
#define FrameworkBundle  [NSBundle bundleWithPath:FrameworkPath]

//得到資源的bundle路徑
#define VivienBundle [NSBundle bundleWithPath:[FrameworkBundle pathForResource:@"questionimages" ofType:@"bundle"]]


//獲取資源路徑,文件實例:
NSString *plistPath = [VivienBundle pathForResource:@"QuestionnaireList" ofType:@"plist"];

但是如果用上面的訪問方式,最后生成framework,在使用時,資源讀取會失敗;導致我在生成framework庫前,又要更改資源的讀取方式,不知道是哪里有問題沒有設置好,有知道的仁兄指點一二.

一些基本設置說明:

-ObjC

我們知道在Objective-C中方法調用都是在運行期確定的,所以Objective-C沒有針對每個方法定義鏈接符號,它只每個類創(chuàng)建鏈接符號。因此當在一個靜態(tài)庫中使用類別來擴展已有類的時候,鏈接器不知道如何把類原有的方法和類別中的方法整合起來,就會導致你調用類別中的方法時出現(xiàn)selector not recognized的錯誤。
設置ObjC標志后,鏈接器會把一個類相關的所有目標文件都加載進來,這樣就解決了這個問題。由于這樣做會使可執(zhí)行文件體積變大,所以需要需要自己手動設置一下。
官方的說明鏈接:https://developer.apple.com/library/archive/qa/qa1490/_index.html
參考鏈接:http://www.itdecent.cn/p/fb5083f2c0d2

-all_load 和 -force_load

在64位ios應用環(huán)境下,在靜態(tài)庫中只有category而沒有對應的class定義時-ObjC標志會失效(這是鏈接器的一個bug)
這時可以使用-all_load強制加載所有目標文件 或者使用-force_load指定加載某一個包
千萬不要隨便使用這個參數(shù)!假如你使用了不止一個靜態(tài)庫文件,然后又使用了這個參數(shù),那么你很有可能會遇到ld: duplicate symbol錯誤,因為不同的庫文件里面可能會有相同的目標文件
所以建議在遇到-ObjC失效的情況下使用-force_load參數(shù)

-force_load所做的事情跟-all_load其實是一樣的
但是-force_load需要指定要進行全部加載的庫文件的路徑
這樣的話,你就只是完全加載了一個庫文件,不影響其余庫文件的按需加載

2021.01.13新增:模擬器包含arm64打包合并問題

只需要對模擬器的.a進行處理即可,終端輸入如下

lipo 路徑/XXX.a -remove arm64 -output  路徑/XXX.a
最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

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