iOS連接庫的衝突

最近在打包的時候,遇到一個坑。特此記錄一下html

 

原由是發現 Unity 5.4 版本,使用c#寫的下載,下載速度沒法突破 2M/s,一樣的網絡,後來橫向對比使用原來 Cocos2d 開始的遊戲,能夠達到 7M/s。海外推廣通常是小包(iOS是150M之內,安卓50M之內) + 擴展包,若是下載速度過慢,對市場推廣和用戶轉化都會有影響(下載等待時間變長了)。而後就決定基於 libcurl 寫了一個C++的下載模塊,以替換現有的 C# 下載模塊。git

 

韓國版本在添加了下載模塊進行測試時,遇到了崩潰。使用 Release Run 時,在下載補丁那裏必崩(編譯是正常的),崩潰的地方是在 curl_easy_init 就掛掉了,很神奇。github

 

最初懷疑是庫的添加順序,嘗試調整順序後發現不是。而後使用排除法,刪相關的庫,發現有一個庫看上去有點奇怪,解壓出來發現裏面引用了 OpenSSL庫,而咱們的下載模塊也用到了這個庫。到這裏緣由就找到了,由於.a靜態庫與 第三方的 framework 有衝突(咱們使用4個.a文件)。解決方案就是使用 .framework動態庫,將4個.a整合成一個動態的.framework,而後添加到Xcode裏。c#

 

問題解決後,在網上搜索了相關的資料。把相關的知識再從新梳理一遍。api

 

庫(Library)分爲:靜態連接庫、動態連接庫,下面將三大主流平臺動態、靜態庫作一個簡單的對比。 xcode

平臺網絡

靜態庫app

動態庫curl

Windows *.lib *.dll
Linux *.a *.so
Mac OS *.a,*.framework *.dylib,*.tbd,*.framework

你可能會奇怪,爲啥 *.framework 既是動態庫又是動態庫,系統的 framework 是動態庫(Real Framework),咱們創建的 framework 是靜態庫(或者稱爲僞動態庫 —— Fake Framework)。函數

 

下面是二個連接,使用 Xcode  build 出 iOS 可以使用的 Framework

https://github.com/kstenerud/iOS-Universal-Framework

https://github.com/jverkoey/iOS-Framework

 

iOS 系統的 UIKit.framework 不須要拷貝到目標程序中,咱們生成的 Framework 即使是動態的,最後仍是須要拷貝到App中,所以蘋果又把這種 framework 稱爲 Embedded Framework。

 

爲何這麼修改就能夠了呢?  iOS中的Embedded Framework能夠理解爲獨立的沒有main函數的可執行文件。這樣就避免衝突了

 

注:須要注意的是 iOS 8以前是不支持動態庫的,只支持靜態庫。

image

 

不然,會報錯。

dyld: Library not loaded: @rpath/xx.framework/xx

Referenced from: /var/containers/Bundle/Application/xxx/xx.app/app

Reason: image not found

 

每次手工將 framework 拖到 xcode確定是很蛋疼的,增好 Unity 提供了 Xcode API 來解決這個問題。

使用  PBXProjectExtensions 類的 AddFileToEmbedFrameworks 方法

https://docs.unity3d.com/ScriptReference/iOS.Xcode.Extensions.PBXProjectExtensions.html

 

using UnityEditor.iOS.Xcode.Custom;

string targetName = PBXProject.GetUnityTargetName();
PBXProject proj = new PBXProject();
proj.ReadFromString(File.ReadAllText(projPath));
string target = proj.TargetGuidByName(targetName);

string strOSVersion = PlayerSettings.iOS.targetOSVersionString;
string strMajorVersion = strOSVersion.Split('.')[0];
if (int.Parse(strMajorVersion) >= 8)
{
    proj.AddFileToBuild(target, proj.AddFile("Frameworks/xx.framework", "Frameworks/xx.framework", PBXSourceTree.Source));    

    const string defaultLocationInProj = "Frameworks/xx/";
    const string coreFrameworkName = "xx.framework";

    string framework = Path.Combine(defaultLocationInProj, coreFrameworkName);
    string fileGuid = proj.AddFile(framework, "Frameworks/" + framework, PBXSourceTree.Sdk);

    PBXProjectExtensions.AddFileToEmbedFrameworks(proj, target, fileGuid);
}

 

 

 

更多參考連接:

iOS靜態庫的連接與加載

iOS動態庫、靜態庫及使用場景、方式

相關文章
相關標籤/搜索