在Swift 5.1中,两种混编的实现步骤:
Swift访问OC:只需要在桥接文件(ProductName-Bridging-Header.h)中导入需要暴露给Swift的OC类,即可在Swift中访问相应OC类及方法。
OC访问Swift:在OC类中导入ProductName-Swift.h文件(Target名称不同,对应文件名称也不同,工程配置中能看到),即可访问Swift中暴露给OC的属性和方法。
我们以一个OC工程为宿主。我们实现一下在Swift类中访问OC,首先,创建一个空工程:
在工程中创建一个Swift类:
由XCode引导而创建桥接文件:
在桥接文件中导入OC类的头文件:
我们再来看一下在这个宿主工程中,OC类中访问Swift,在工程配置的Build Settings中搜索Swift Compiler,可以看到Swift与OC混编的两个配置文件:
在想要访问Swift方法的OC类中导入ProductName-Swift.h(手动输入没有提示,并且在编译之前报红),然后编译一下:
即可在ViewController这个OC类中调用Swift:
本例中,点入头文件QiHybridCompile-Swift.h,在工程里看一下他的定义:
// Swift语言
@objcMembers class Cat: NSObject {
var name: String
init(name: String) {
self.name = name
}
@objc(oc_test) func test() {
print("test")
}
}
首先,创建一个封装framework的Swift工程,名为"QiSwiftSdk.xcodeproj",并将它拖进宿主工程中。然后,在宿主工程配置中的BuildPhase下,设置工程依赖关系,如下图:
本例中,在OC的宿主工程中创建一个Swift类"QSSdkTest",并写了两个测试方法,则调用Swift库时的代码如下:
注意:
NS_SWIFT_NAME: 在Objective-C中,重新命名在swift中的名称。
NS_SWIFT_UNAVAILABLE:在swift中不可见,不能使用。
对于自定义的类而言,Objective-C的类不能继承自Swift的类,即要混编的OC类不能是Swift类的子类。反过来,需要混编的Swift类可以继承自OC的类。
如果需要在 oc 类中使用时只能使用带@objc的枚举,带@objc的枚举必须时 Int 类型,否则会报错。
@objc enum Direction: Int {
case Up
case Down
case Left
case Right
}
只有像上面定义的 Swift 枚举才能在 oc 类中使用。
swift 中没有 “|”,如,下面写法是错误的
let options : NSStringDrawingOptions = .UsesLineFragmentOrigin | .UsesFontLeading
可以直接写成
let options : NSStringDrawingOptions = [.UsesLineFragmentOrigin, .UsesFontLeading]
//OC代码
typedef NS_ENUM(NSInteger, PlayerState) {
PlayerStateNone = 0,
PlayerStatePlaying,
PlayerStatePause,
PlayerStateBuffer,
PlayerStateFailed,
};
typedef NS_OPTIONS(NSUInteger, XXViewAnimationOptions) {
XXViewAnimationOptionNone = 1 << 0,
XXViewAnimationOptionSelcted1 = 1 << 1,
XXViewAnimationOptionSelcted2 = 1 << 2,
}
enum PlayerState: Int {
case none = 0
case playing
case pause
case buffer
case failed
}
struct ViewAnimationOptions: OptionSet {
let rawValue: UInt
static let None = ViewAnimationOptions(rawValue: 1<<0)
static let Selected1 = ViewAnimationOptions(rawValue: 1<<0)
static let Selected2 = ViewAnimationOptions(rawValue: 1 << 2)
//...
}
Swift没有NS_OPTIONS的概念,取而代之的是为了满足OptionSet协议的struct类型。
如果你在一个Swift类里定义了一个delegate方法:
@objc protocol MarkButtonDelegate {
func clickBtn(title: String)
}
如果你要在OC中实现这个协议,这时候方法名就变成了:
- (void)clickBtnWithTitle:(NSString *)title {
// code
}
如果要在 oc 中使用 swift 定义的协议,则需要加上@objc,且如果是不必实现的函数,函数前要加上 @objc optional。
@objc protocol AlertViewProtocol {
func submit(_ row: Int) //必须实现的协议
@objc optional func cancel() //不必实现的协议
}
元组:对于 oc 可能用到的:方法,返回不能是元组,参数不能是元组。属性不能是元组。
范型(Generics)范型
Swift 中定义的结构体(Structures defined in Swift)不能在 oc 中使用,OC 中必须继承 NSObject(OC 不能使用 Swift 结构体)
Swift 中定义的高阶函数 (比如 filter, map 等)
Swift 中定义的全局变量(Global variables defined in Swift)
Swift 中定义的类型别名(Typealiases defined in Swift)
Swift 风格可变参数(Swift-style variadics)
嵌套类型(Nested types)
柯里化函数(Curried functions)