开发集锦

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

2021-11-06  本文已影响0人  Fat君

装模作样写个前言

背景:拥有悠久历史的大型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)")
    }
}

解释一下:

|在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

|我们来比对一下加入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

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混编(下)

上一篇 下一篇

猜你喜欢

热点阅读