16、OC与Swift的混编

16、OC与Swift的混编

  • 1、在同一个工程中的混编
    • Swift访问OC
      • 注意事项:
    • OC调用Swift
      • 注意事项
  • framework和宿主APP之间的混编
  • 其他注意事项
    • NS_SWIFT_NAME和NS_SWIFT_UNAVAILABLE
    • Subclass
    • swift 枚举类型在 oc 中使用
    • swift 中使用 oc 的 NS_OPTIONS 类型枚举
    • enum枚举
    • 函数名的变化
    • oc 使用 swift 定义的协议
    • swift 中有而 oc 中没有的

在使用Swift进行iOS开发的过程中,经常涉及到Swift与OC混编的情况,有时主工程是OC的需要另外编入Swift代码,而有时主工程是Swift的需要另外编入OC代码。这其中涉及到修改一下XCode的工程配置。

1、在同一个工程中的混编

在Swift 5.1中,两种混编的实现步骤:

  • Swift访问OC:只需要在桥接文件(ProductName-Bridging-Header.h)中导入需要暴露给Swift的OC类,即可在Swift中访问相应OC类及方法。

  • OC访问Swift:在OC类中导入ProductName-Swift.h文件(Target名称不同,对应文件名称也不同,工程配置中能看到),即可访问Swift中暴露给OC的属性和方法。

Swift访问OC

我们以一个OC工程为宿主。我们实现一下在Swift类中访问OC,首先,创建一个空工程:
16、OC与Swift的混编_第1张图片
在工程中创建一个Swift类:
16、OC与Swift的混编_第2张图片

由XCode引导而创建桥接文件:
16、OC与Swift的混编_第3张图片
在桥接文件中导入OC类的头文件:

16、OC与Swift的混编_第4张图片

注意事项:

OC调用Swift

我们再来看一下在这个宿主工程中,OC类中访问Swift,在工程配置的Build Settings中搜索Swift Compiler,可以看到Swift与OC混编的两个配置文件:
16、OC与Swift的混编_第5张图片
在想要访问Swift方法的OC类中导入ProductName-Swift.h(手动输入没有提示,并且在编译之前报红),然后编译一下:
16、OC与Swift的混编_第6张图片
即可在ViewController这个OC类中调用Swift:
16、OC与Swift的混编_第7张图片
本例中,点入头文件QiHybridCompile-Swift.h,在工程里看一下他的定义:
16、OC与Swift的混编_第8张图片

注意事项

  • Swift类要给OC使用,需要继承自NSObject,并且使用@objc修饰需要暴露给OC使用的成员,或者使用@objcMembers修饰类将所有成员暴露给OC。Swift代码中可以使用@objc重命名暴露给OC的符号名(类名,属性名,函数名等)
  • Swift类中用public修饰过的方法,才会出现在ProductName-Swift.h文件中;
  • 所有Swift类在ProductName-Swift.h文件都会被自动注册,也会自动@interface修饰,ProductName-Swift.h文件会自动更新。
// Swift语言
@objcMembers class Cat: NSObject {
     
    var name: String
    
    init(name: String) {
     
        self.name = name
    }
  
    @objc(oc_test) func test() {
     
        print("test")
    }
}

framework和宿主APP之间的混编

首先,创建一个封装framework的Swift工程,名为"QiSwiftSdk.xcodeproj",并将它拖进宿主工程中。然后,在宿主工程配置中的BuildPhase下,设置工程依赖关系,如下图:
16、OC与Swift的混编_第9张图片
本例中,在OC的宿主工程中创建一个Swift类"QSSdkTest",并写了两个测试方法,则调用Swift库时的代码如下:
16、OC与Swift的混编_第10张图片
注意:

  • Swift库中所要暴露的类,类前需要使用关键字open修饰;
  • Swift库某个类中供OC调用的方法,依然要用@objc public修饰;
  • 本例默认的头文件"QiSwiftSdk.h"中,没有做任何操作;
  • Swift库中也可以混编,Swift库的工程配置中也桥接文件的相关配置。

其他注意事项

NS_SWIFT_NAME和NS_SWIFT_UNAVAILABLE

NS_SWIFT_NAME: 在Objective-C中,重新命名在swift中的名称。
NS_SWIFT_UNAVAILABLE:在swift中不可见,不能使用。
16、OC与Swift的混编_第11张图片

Subclass

对于自定义的类而言,Objective-C的类不能继承自Swift的类,即要混编的OC类不能是Swift类的子类。反过来,需要混编的Swift类可以继承自OC的类。

swift 枚举类型在 oc 中使用

如果需要在 oc 类中使用时只能使用带@objc的枚举,带@objc的枚举必须时 Int 类型,否则会报错。

@objc enum Direction: Int {
     
    case Up
    case Down
    case Left
    case Right
}

只有像上面定义的 Swift 枚举才能在 oc 类中使用。

swift 中使用 oc 的 NS_OPTIONS 类型枚举

swift 中没有 “|”,如,下面写法是错误的

let options : NSStringDrawingOptions = .UsesLineFragmentOrigin | .UsesFontLeading

可以直接写成

let options : NSStringDrawingOptions = [.UsesLineFragmentOrigin, .UsesFontLeading]

enum枚举

//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 定义的协议

如果要在 oc 中使用 swift 定义的协议,则需要加上@objc,且如果是不必实现的函数,函数前要加上 @objc optional。

@objc protocol AlertViewProtocol {
     
    func submit(_ row: Int) //必须实现的协议
    @objc optional func cancel() //不必实现的协议
}

swift 中有而 oc 中没有的

元组:对于 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)

你可能感兴趣的:(Swift,1024程序员节)