装模作样写个前言
背景:拥有悠久历史的大型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.h 和 SWSDK.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化方法
网友评论