Swift 調用 OC 實用技巧 Swift App Swift Framework

Swift App

混入OC/C/C++代碼

方法一

使用橋接文件。

方法二

使用.modulemap

  1. Swift App項目,引入OC/C/C++文件。
  2. 創建文件名必須爲module 後綴爲.modulemap的文件。
  1. 配置工程BuildSettingSwift Compiler - Search Paths選項,值爲module.modulemap文件所在的目錄路徑或其上層目錄路徑。

此處可爲:

${SRCROOT}/MixFrameworkTest
${SRCROOT}/MixFrameworkTest/ObjcInSwitApp

如果這裏的路徑配置不正確便會報錯:error build: No such module '*'

4.配置module.modulemap內容

module OcInApp {
    // 所引入頭文件相對於`.modulemap`的路徑; "./OcClassInApp.h"也可以
    header "OcClassInApp.h" 
    export *
}
  1. import導入使用
import OcInApp
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        OcClassInApp.description()
    }
}

混入OC Framework

如果引入的OC FrameWork中含有Modules/module.modulemap文件,則直接拖入Swift工程中,使用import引入並進行調用即可。

如果OC FrameWork不支持modulemap(沒有module.modulemap文件),則有兩種方法:

方法一

建立橋接文件,按需導入頭文件

方法二

基於OC FrameWork/Modules/module.modulemap路徑,創建module.modulemap文件,並輸入以下內容並保存,之後便可使用import引入並進行調用。

// 按需導入
framework module SameAsFrameWorkName { //必須與導入的`OC Framework`同名
  header "A.h"
  header "B.h"
  header "b.h"
  //..
  export *
}
///遞歸導入
framework module SameAsFrameWorkName { //必須與導入的`OC Framework`同名
  umbrella header "SameAsFrameWorkName.h" //SDK對外頭文件,包含SDK對外暴露的諸多.h文件

  export *
  module * { export * }
}

混入OC xcframework

與混入OC framework操作基本一致,如果引入的OC xcframework下不同的架構文件下的framework中含有Modules/module.modulemap文件,則直接拖入Swift工程中,使用import引入並進行調用即可。

如果OC xcframework不支持modulemap,也是有兩種方法:

方法一

建立橋接文件,按需導入頭文件。

方法二

OC xcframework下不同架構framework,參考混入OC framework的方法二,即可調用。

Swift Framework

Swift Framework僅有Swift類時,如果是需要SDK外部使用的ClassMethod,則只需要使用publicopen修飾。

Swift工程導入Swift Framework後,直接在Swift的工程中使用即可。

import RadarSDK
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        RadarEntry.start()
    }
}

注意:Swift Framework中是不支持使用橋接文件的,不然的話會報錯:

混入OC/C/C++代碼

示例工程結構如下:

內部使用 OC

SDK內部的Swift類,不能直接使用OC的代碼,並且不支持橋接文件。因此只能使用module.modulemap文件

  1. 創建文件名必須爲module 後綴爲.modulemap的文件。
  2. 配置工程BuildSettingSwift Compiler - Search Paths選項,值爲module.modulemap文件所在的目錄路徑或其上層目錄路徑,此處可爲:
${SRCROOT}/SwiftMixSDK/ObjcSources
${SRCROOT}/SwiftMixSDK
  1. 配置module.modulemap內容
module ObjcInFramwork {
    header "ObjcClassA.h"
    header "ObjcClassB.h"
    export *
}
  1. 使用
import ObjcInFramwork
public class SwiftMixTest: NSObject {
   public static func mixTest() {
        ObjcClassA.description()
        print("Swift MixIn OC")
    }
}

外部使用OC

如果Swift Framework外部需要調用混入的OC,有兩種方法:

方法一

Swift Framework外接.h頭文件以#import <SwiftMixSDK/PublicHeader.h>的方法對外公開需要使用的OC頭文件。

  1. 配置 Frame Targetbuild Phases,使得OC頭文件公開


  1. Swift Framework外接.h文件import需要公開的OC頭文件
  1. 使用
import UIKit
import SwiftMixSDK
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        SwiftMixTest.mixTest()
        ObjcClassA.description()
        ObjcClassB.description()
    }
}
  1. 編譯最終產物對外暴露的頭文件


方法二

自定義Swift Framework.modulemap文件。

  1. 自定義module.modulemap文件;此處的文件名不強制module,但建議用module,因爲編譯器最終會合並自定義的文件,最終導出module.modulemap文件。
  2. 配置 Frame Targetbuild Setting,保證Define ModuleYES; Module Map File 爲自定義.modulemap文件的路徑。
  1. 配置module.modulemap內容
framework module SwiftMixSDK {
    umbrella header "SwiftMixSDK.h"
    export *
    module * {export *}
    module ObjcInFramwork {
        header "/Users/*/Desktop/*/SwiftSDKExample/SwiftMixSDK/ObjcSources/ObjcClassA.h"
        header "/Users/*/Desktop/*/SwiftSDKExample/SwiftMixSDK/ObjcSources/ObjcClassB.h"
        export *
    }
}

最終SDKmodulemap:

值得注意的是,此處的header,只能使用絕對路徑,否則會出錯。 stackoverflow此問題的QA

  1. 使用
import UIKit
import SwiftMixSDK.ObjcInFramwork
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        SwiftMixTest.mixTest()
        ObjcClassA.description()
        ObjcClassB.description()
    }
}
  1. 編譯最終產物對外暴露的頭文件

小結

綜上可以看出,兩種方法編譯的最終產物存在差異:

方法一會暴露OC頭文件的;方法二會隱藏OC的頭文件。
多人協作開發Swift Framework時,方法二會存在頻繁修改.modulemap文件文件。因此實際開發中還得基於項目決定方案。

混入OC Framework

OC Framework不支持Module時,有兩種方式混入OC Framework

方法一

通過使用.modulemap文件,實現對OC Framework調用。即:OC Framework支持(自動或者手動)module

方法二

參考上述 混入OC/C/C++代碼 —— 內部使用OC ,創建module.modulemap文件,配置相關Building Setting。配置module.modulemap內容如下:

module ObjcFramwork {
    ///相對於module.modulemap的相對路徑
    umbrella header "../ObjcFramwork.framework/Headers/ObjcFramwork.h"
    export *
    module * { export * }
}

最後在Swift文件中import ObjcFramwork,即可調用。

混入OC xcframework

OC xcframework不支持Module時,有兩種方式混入OC xcframework

方法一
OC xcframework下不同架構framework,參考混入OC Framework方法一,進行操作後即可調用。

方法二

參考上述 混入OC/C/C++代碼 —— 內部使用OC ,創建module.modulemap文件,配置相關Building Setting

這些操作與混入OC Framework方法二一致,唯一有區別在於:OC xcframework包含多種架構的Framework

因此不能通過相對路徑直接引入,因爲不同架構路徑下的同一個頭文件會相互覆蓋而報錯;

如何解決呢?我們可以通過新建一個ObjcXCFramwork-umbrella.h文件(可以是其它名稱),並在其中引入xcframework的頭文件:

#import <MyTestSDK/MyTestSDK.h>

然後配置module.modulemap內容如下:

module ObjcXCFramwork {
  umbrella header "ObjcXCFramwork-umbrella.h"

  export *
  module * { export * }
}

最後在Swift文件中import ObjcXCFramwork,即可調用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章