最近在打包的時候,遇到一個坑。特此記錄一下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以前是不支持動態庫的,只支持靜態庫。
不然,會報錯。
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); }
更多參考連接: