最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

Swift与OC混编

来源:博客园


(资料图片)

Swift调OC在Swift项目中调用OC类中的方法需要有个{targetName}-Bridging-Header.h文件,在这个文件中导入OC要暴露给Swift的类。{targetName}-Bridging-Header.h文件的创建有2种方式1.自己手动创建,然后在配置文件的Object-C Bridging Header中添加这个{targetName}-Bridging-Header.h文件的路径2.在Swift项目工程中创建一个OC类,此时Xcode会自动帮助创建。3.在Swift中使用OC类
import UIKitclass ViewController: UIViewController {    override func viewDidLoad() {        super.viewDidLoad()        // Do any additional setup after loading the view.        let p = Person();        p.name = "jack";        p.age = 11;        p.say();    }}
如果自己在OC中定义的C语言函数名字和Swift运行中的函数名一样,冲突时,可以使用@_silgen_name将C函数的名字进行重新成Swift的另一个函数名,供Swift中使用。
@_silgen_name("sum") func swift_sum(a: Int, b: Int) -> Int
OC调SwiftSwift项目在创建时就默认生成了一个{targetName}-Swift.h文件,用于暴露Swift类给OC使用。注意这里的targetName不允许使用-链接单词,如果出现这种情况会把-自动改成_进行单词连接。如下,当前项目名是Swift-OC,而targetName被自动改成了Swift_OC。Swift暴露给OC类使用时需要做一定的修改。1.要暴露的类需要继承自NSObject2.要暴露成员变量和方法给OC时,需要加@objc声明。3.要暴露全部信息时,包含成员变量和方法以及扩展中的信息,则要在类前面加@objcMembers进行声明。
@objcMembers class Car: NSObject {    var speed: Float;    var name: String;        init(speed: Float, name: String) {        self.speed = speed;        self.name = name;    }        func run() -> Void {        print("出发,时速:\(self.speed)")    }}extension Car {    func circleRun() {        print("跑圈,时速:\(self.speed)")    }}
Swift中@objc的使用可以使用@objc重命名swift暴露给oc的方法selector是oc的runtime里使用的一套东西,只有swift中的类暴露给OC是才能正常使用。
@objcMembers class Car: NSObject {    var speed: Float;    @objc(bigName) //重写暴露给OC的方法    var name: String;        init(speed: Float, name: String) {        self.speed = speed;        self.name = name;    }        func run() -> Void {        print("出发,时速:\(self.speed)")    }        func runPerform() -> Void {        perform(#selector(run))    }}extension Car {    @objc(bigRun)    func circleRun() {        print("跑圈,时速:\(self.speed)")    }}
Swift中被@objc 修改的协议可以被OC实现
@objc protocol RunProtocol {}
Swift的类中中被@objc dynamic 修改的方法 走runtime的那套消息发送机制
class Computer: NSObject {    @objc dynamic func work(num: Int) {        print("工作时长:\(num)")    }}
Swift的类中中被@objc dynamic 修改的属性可以进行KVC/KVO
class Person: NSObject {    @objc dynamic var age: Int = 10        override init() {        super.init()        self.addObserver(self, forKeyPath: "age", options: .new, context: nil)    }        override class func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {        print("observer回调:\(change!)")    }        deinit {        self.removeObserver(self, forKeyPath: "age")    }}
Swift与OC互相调用理解1.Swift要暴露给OC调用,为什么要继承自NSObject?OC的方法调用走的runtime的objc_sendMsg(), 这就需要isa指针, 而NSObject中有isa指针,所以要继承自NSObject2.Swift调用OC桥接类的方法是怎么调用的,OC调用Swift暴露的方法又是如何调用的?Swift调用自己定义的纯Swift方法底部走的是C++虚函数表那套。Swift调用OC桥接类的方法底层走的还是OC的objc_msgSender机制,因为OC文件被编译后是转换的消息发送代码。OC调用Swift暴露的方法时,因为是继承自NSObject, 所以底部走的还是objc_sendMsg机制3.对于Swift类继承了NSObject,再在swift调用时,是怎么调用的?底层走的还是Swift的需函数表那套,这套性能更高。如何让Swift的方法走Runtime的消息转发机制呢?通过在方法前面添加dynamic修饰
@objcMembers class Car: NSObject {    var speed: Float;    @objc(bigName) //重写暴露给OC的方法    var name: String;        init(speed: Float, name: String) {        self.speed = speed;        self.name = name;    }            dynamic func fillOil() -> Void {        print("加油")    }}

关键词: