美文网首页开发集锦
从零开始编写iOS混编SDK(中)

从零开始编写iOS混编SDK(中)

作者: Fat君 | 来源:发表于2021-11-06 16:54 被阅读0次

    装模作样写个前言

    背景:拥有悠久历史的大型SDK,这个历史当然是Objective-C。又当然这个是没有问题的,而且每天都在服务上千万用户,但是不巧的是Apple出了一个StoreKit2,按理说每年苹果爸爸都要出很多API,这很正常。但是又不巧的是它只支持 Swift 编写,而且这样的API我估计只会成为常态,所以 Swift 化已经刻不容缓了。

    结果:半夜执笔

    温馨提示:本文实例代码已上传github,附录于(下)中。

    编译环境:Xcode13.0 Swift5.5 arm64

    如有不正,请在评论区告知我。

    一、 在SDK内部OC调用Swift

    |新建两个 Swift 文件

    import UIKit
    
    @objc(TESTSWIFT)
    @objcMembers
    public
    class TestSwift: NSObject {
        public static func run() -> Void {
            print("(#fileID): (#function)")
            TestSwift2.run()
        }
    }
    
    
    //TestSwift2.swift
    
    
    class TestSwift2: NSObject {
        static func run() -> Void {
            print("(#fileID): (#function)")
        }
    }
    

    解释一下:

    • @objc 在这里主要是为了修改类的名称。

    • @objcMembers在类名前面是使用objcMembers修饰,系统会在自动给这个类的所有方法添加@objc,暴露给OC。

    • public 是为了暴露给外部OC调用者。

    |在OC中调用该Swift类

    #import "TestOC.h"
    #import "TestOC2.h"
    #import <SWSDK/SWSDK-Swift.h>
    @implementation TestOC
    
    + (void) run  {
        NSLog(@"TestOC:SDK外放OC类");
        [TESTSWIFT run];
        [TestOC2 run];
    }
    
    @end
    
    • 这里主要操作是 #import <SWSDK/SWSDK-Swift.h>, 所有OC调用 Swift 的地方必须导入该头文件,为了方便导入,我们可以在 PCH 文件中加入该头文件。

    • 我们可以看到Swift内部类不需要添加 @objc、@objcMembers、public 等关键词。

    |我们来比对一下加入Swift前后的文件结构变化

    . //无Swift
    ├── Headers
    │   ├── SWSDK.h
    │   └── TestOC.h
    ├── Info.plist
    ├── Modules
    │   └── module.modulemap
    ├── SWSDK
    └── _CodeSignature
        ├── ...
    
    
    . //增加Swift
    ├── Headers
    │   ├── SWSDK-Swift.h
    │   ├── SWSDK.h
    │   └── TestOC.h
    ├── Info.plist
    ├── Modules
    │   ├── SWSDK.swiftmodule
    │   │   ├── ...
    │   └── module.modulemap
    ├── SWSDK
    └── _CodeSignature
        ├──...
        
    
    //SWSDK-Swift.h文件
    SWIFT_CLASS_NAMED("TestSwift")
    @interface TESTSWIFT : NSObject
    + (void)run;
    - (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;
    @end
    
    • 增加了 SWSDK-Swift.hSWSDK.swiftmodule 目录。 PS: Swiftmodule文件夹需要模拟器与真机合并才可以对外使用。

    • SWSDK-Swift.h 主要是为了方便内部OC调用。这里 Headers 的增加: 没有进行Build Phases 的 public 拖拽,属于自动外放。

    • SWSDK.swiftmodule:公共接口的定义文件。


    Question:有人可能有疑问,为什么SWSDK-Swift.h变成外放了?

    |我们一起来看看modulemap文件的前后变化

    framework module SWSDK { 
      umbrella header "SWSDK.h"
    
      export *
      module * { export * }
    }
    
    //加入Swift后新增的SWSDK.Swift
    module SWSDK.Swift {
        header "SWSDK-Swift.h"
        requires objc
    }
    

    |所以内部可以调用SWSDK-Swift.h,由 modulemap 外放到 Headers 中,所以按逻辑来说,在外部工程中也可以显式的调用 SWSDK-Swift.h。

    在AppDelegate.h中调用
    #import "AppDelegate.h"
    //#import <SWSDK/SWSDK.h>
    #import <SWSDK/SWSDK-Swift.h>
    @interface AppDelegate ()
    @end
    @implementation AppDelegate
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //    [TestOC run];
        [TESTSWIFT run];
        return YES;
    }
    
    //输出
    SWSDK/TestSwift.swift: run()
    SWSDK/TestSwift2.swift: run()
    

    |所以外部类也可以正常调用Swift,只需要加上 #import<SWSDK/SWSDK-Swift.h> 头文件。

    下一篇我们将介绍SDK内部Swift调用OC的Module化方法

    在Objective-C的SDK内部采用Swift混编(下)

    相关文章

      网友评论

        本文标题:从零开始编写iOS混编SDK(中)

        本文链接:https://www.haomeiwen.com/subject/rlujzltx.html