溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Flutter?iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決

發(fā)布時間:2022-07-21 09:53:45 來源:億速云 閱讀:476 作者:iii 欄目:開發(fā)技術(shù)

本文小編為大家詳細介紹“Flutter iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決”,內(nèi)容詳細,步驟清晰,細節(jié)處理妥當,希望這篇“Flutter iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學(xué)習(xí)新知識吧。

OC接入Swift 插件

首先,當我在一個 OC 項目里接入一個 Swift 插件,可能會遇到什么問題?

如下圖所示,如果你是一個比較老的 Flutter 項目,那可能會出現(xiàn) swift 插件出現(xiàn) not found 的問題。

Flutter?iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決

針對這個問題,一般都是建議在 Podfile 文件下添加 use_frameworks! ,有時候還會建議添加 use_modular_headers! ,那這兩個標記位的作用是什么?

target 'Runner' do
  use_frameworks! 
  use_modular_headers!
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

我們知道 Podfile 的作用是處理 CocoaPads ,而 use_frameworks!告訴 CocoaPods 你想使用 Framework 而不是靜態(tài)庫,而默認由于 Swift 不支持靜態(tài)庫,因此有一開始 Swift 必須使用 Framework 的限制。

靜態(tài)庫和 Framework 區(qū)別

靜態(tài)庫和 Framework 的區(qū)別在于:

  • *.a 的靜態(tài)庫類似于編譯好的機械代碼,源代碼和庫代碼都被整合到單個可執(zhí)行文件中,所以它會和設(shè)備架構(gòu)綁定,并且不包含資源文件比如圖片;

  • Framework 支持將動態(tài)庫、頭文件和資源文件封裝到一起的一種格式,其中動態(tài)庫的簡單理解是:不會像靜態(tài)庫一樣被整合到一起,而是在運行或者運行時動態(tài)鏈接;

另外一個配置 use_modular_headers! ,它主要是將 pods 轉(zhuǎn)為 Modular,因為 Modular 是可以直接在 Swift中 import ,所以不需要再經(jīng)過 bridging-header 的橋接。

但是開啟 use_modular_headers! 之后,會使用更嚴格的 header 搜索路徑,開啟后 pod 會啟用更嚴格的搜索路徑和生成模塊映射,歷史項目可能會出現(xiàn)重復(fù)引用等問題,因為在一些老項目里 CocoaPods 是利用Header Search Paths 來完成引入編譯,當然使用 use_modular_headers!可以提高加載性能和減少體積。

繼續(xù)回到問題上,我們在添加完 use_frameworks! 之后,有一定幾率中獎各種 Undefined symbol 的錯誤問題,這時候不要慌,因為這是 Swfit 里有靜態(tài)庫導(dǎo)致。

Flutter?iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決

很明顯 Swift 不支持靜態(tài)庫的行為不科學(xué),所以從 Xcode 9 開始 Swift 就開始支持靜態(tài)庫,而 CocoaPods 1.9.0 開始,引入了 use_frameworks! :linkage => :static 來生支持有靜態(tài)庫和 Framework 的情況。

新的問題: non-modular heade

所以修改 use_frameworks 配置,增加 static 之后可以看到 Undefined symbol 的錯誤都消失了,但是運行之后,可能會喜提新的問題: non-modular header 。

Flutter?iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決

如果你去搜索答案,有很多答案會告訴你如下圖所示,通過 Allow Non-modular Includes in Framework Modules 設(shè)置為 true 就可以解決問題,但是很明顯這并不是正解,它更多適用于臨時的緊急狀體下。

Flutter?iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決

當然,你也可以在出現(xiàn)問題的插件的 .podspec 下單獨配置 ALLOW ,效果相同,更輕量級,但是這也只是臨時解決方案。

s.user_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' }

為什么說這種方式不靠譜,因為你不知道官方會什么時候刪除這種允許,當然這個問題網(wǎng)友提供的解決方案其實千奇百怪:

  • 如果是 App 使用 dynamic framework 里的 header 導(dǎo)致錯誤,可以使用 #import "MyFile.h" 而不是 #import <MyFramework/MyFile.h> ;

  • #import語句移到 .m(而不是將其放在.h頭文件中), 這樣它就不會有包含 non-modular header 的問題,例如: github.com/AFNetworkin&hellip; ;

  • 重命名 header ,不要讓 header 和模塊名一樣,變?yōu)?#import <FrameworkName/Header.h>

  • 在 build setting 配置 OTHER_SWIFT_FLAGS -Xcc -Wno-error=non-modular-include-in-framework-module 解決 Swift 的問題;

有可能它們都能解決你的問題,但是為什么呢?下次遇到這些問題要選哪個解決?

不能在Framework Module中使用非Modular 的 Header

回歸到我們的問題,其實我的問題關(guān)鍵是:不能在 Framework Module 中使用非 Modular 的 Header,也就問題是在 Framework Module 中加載了非當前 Module 的頭文件,而由于 Header 是對外 public ,比如配置到了 s.public_header_files ,就會導(dǎo)致非 Modular 的 Header 也出現(xiàn)對外暴露的風險,所以我這邊的解放方式也很簡單:

*在 s.public_header_files 里只放需要公開的 Plugin.h ,使用了非 Modular 的 Header 不對外 public,從而符合規(guī)范達到編譯成功。

所以這里面的核心是:不要在 Umbrella Header File 中引用不需要對外公開的 OC 頭文件去作為子 module ,這也解釋了為什么上面講出問題的 #import語句移到 .m 就解決問題的邏輯。

例如有時候你還會引用一些系統(tǒng)的 C Module ,其實在 Framework Module 化過程中也會有類似的問題。

所以知道了為什么和怎么解決,就不會只是粗暴通過 LLVM 的配置來設(shè)置 Allow Non-modular Includes in Framework Modules 去解決薛定諤的問題。

另外你可能還有用到的,比如模擬器編譯提示 unsupport arm64、 BITCODE 失敗,SWIFT_VERSION 版本沖突等等:

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
    target.build_configurations.each do |config|
        # building for iOS Simulator, but linking in an object file built for iOS, for architecture ‘a(chǎn)rm64'
        config.build_settings['EXCLUDED_ARCHS[sdk=iphonesimulator*]'] = 'arm64'
        #不支持 BITCODE
        config.build_settings['ENABLE_BITCODE'] = 'NO'
        #解決swift模塊問題
        config.build_settings['SWIFT_VERSION'] = '5.0' 
    end
  end
end

讀到這里,這篇“Flutter iOS開發(fā)OC混編Swift動態(tài)庫和靜態(tài)庫問題怎么解決”文章已經(jīng)介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領(lǐng)會,如果想了解更多相關(guān)內(nèi)容的文章,歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI