美文网首页
【Swift】:OC和Swift混编

【Swift】:OC和Swift混编

作者: 意一ineyee | 来源:发表于2020-01-10 18:25 被阅读0次

一、Swift调用OC
二、OC调用Swift
三、#selector()

写在前面:

  • Swift的方法,在Swift里调用时,走的是Swift的方法调用流程;OC的方法,在OC里调用时,走的是OC的方法调用流程——即消息机制;
  • 但无论是Swift调用OC的方法,还是OC调用Swift的方法,走的都是OC的方法调用流程——即消息机制 。

一、Swift调用OC


文件目录

假设我们有一个用OC写的Person类。

// -----------INEPerson.h-----------
#import <Foundation/Foundation.h>

@interface INEPerson : NSObject

@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *name;

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name;
+ (instancetype)personWithAge:(NSInteger)age name:(NSString *)name;

- (void)run;
+ (void)run;

- (void)eat:(NSString *)food other:(NSString *)other;
+ (void)eat:(NSString *)food other:(NSString *)other;

@end


// -----------INEPerson.m-----------
#import "INEPerson.h"

@implementation INEPerson

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name {

    if (self = [super init]) {
        self.age = age;
        self.name = name;
    }

    return self;
}

+ (instancetype)personWithAge:(NSInteger)age name:(NSString *)name {
    
    return [[self alloc] initWithAge:age name:name];
}

- (void)run {
    
    NSLog(@"%s, %d, %@", __func__, self.age, self.name);
}

+ (void)run {
    
    NSLog(@"%s", __func__);
}

- (void)eat:(NSString *)food other:(NSString *)other {
    
    NSLog(@"%s, %d, %@, %@, %@", __func__, self.age, self.name, food, other);
}

+ (void)eat:(NSString *)food other:(NSString *)other {
    
    NSLog(@"%s, %@, %@", __func__, food, other);
}

@end

如果我们想在Swift的代码里调用这个类,就得首先创建一个Swift和OC的桥接头文件,文件名的格式为:{targetName}-Bridging-Header.h;然后配置一下这个桥接头文件:$(SRCROOT)/项目名/{targetName}-Bridging-Header.h

接下来我们就可以在这个桥接头文件里导入Swift想要调用的OC类了。

// SwiftTest-Bridging-Header.h
#import "INEPerson.h"

现在我们去main.swift里调用一下OC。

// -----------main.swift-----------
/*
 会优先调用-initWithAge:name:
 如果没有-initWithAge:name:,才会去调用+personWithAge:name
 */
var person = INEPerson(age: 11, name: "张三")
person?.age = 12
person?.name = "李四"
person?.run() // -[INEPerson run], 12, 李四
person?.eat("Apple", other: "Banana") // -[INEPerson eat:other:], 12, 李四, Apple, Banana

INEPerson.run() // +[INEPerson run]
INEPerson.eat("Beef", other: "Turkey") // +[INEPerson eat:other:], Beef, Turkey

二、OC调用Swift


文件目录

假设我们有一个用Swift写的Car类。

// -----------main.swift-----------
class Car {
    var price: Double
    var band: String
    
    init(price: Double, band: String) {
        self.price = price
        self.band = band
    }
    
    func run() {
        print("run", self.price, self.band)
    }
    
    static func run() {
        print("Car run")
    }
}

extension Car {
    func test() {
        print("test", self.price, self.band)
    }
}


// 上面OC的INEPerson类里新增了一个C函数testSwift,供Swift调用
testSwift()

如果我们想在OC的代码里调用这个类,也得首先创建一个OC和Swift的桥接头文件,文件名的格式为:{targetName}-Swift.h,只不过系统早就自动帮我们创建好了,但是我们在文件目录里看不到它;然后配置一下这个桥接头文件,只不过系统也早就自动帮我们配置好了:$(SWIFT_MODULE_NAME)-Swift.h。我们什么都不需要干喽,用的时候导入一下这个桥接头文件就可以了(你可以点进去看看,这个桥接头文件里其实会生成一份Swift代码对应的OC代码)。

我们需要做的仅仅是让用Swift写的那个类继承自NSObject,并用@objc关键字修饰一下想要暴露给OC使用的属性和方法,当然如果我们想让这个类全部的属性和方法都能给OC使用,则直接用@objcMembers关键字修饰一下这个类即可 ,此外我们还可以用@objc给Swift的类重命名成OC那种带前缀的类型。

@objc(INECar)
@objcMembers class Car: NSObject {
    @objc var price: Double
    var band: String
    
    init(price: Double, band: String) {
        self.price = price
        self.band = band
    }
    
    @objc func run() {
        print("run", self.price, self.band)
    }
    
    static func run() {
        print("Car run")
    }
}

extension Car {
    func test() {
        print("test", self.price, self.band)
    }
}

现在我们去Person里调用一下Swift的代码。

// -----------INEPerson.h-----------
#import <Foundation/Foundation.h>

void testSwift(); // 新增了一个C函数testSwift,供Swift调用,一运行Swift项目就会触发下面OC的代码了

@interface INEPerson : NSObject

@end


// -----------INEPerson.m-----------
#import "INEPerson.h"
#import "SwiftTest-Swift.h"

void testSwift() {
     
    INECar *car = [[INECar alloc] initWithPrice:15 band:@"雪佛兰"];
    car.price = 30;
    car.band = @"奔驰";
    [car run]; // run 30.0 奔驰
    [car test]; // test 30.0 奔驰
    
    [INECar run]; // Car run
}

@implementation INEPerson 

@end

三、#selector()


Swift里用#selector()定义一个选择器,但是这个方法必须得用@objc修饰一下,或者让这个方法存在于用@objcMembers修饰的类里面也行,这是因为#selector()这种东西是依赖于Runtime的,而Runtime是OC的东西,纯Swift是没有那套完整的Runtime的,所以得搞成OC的。

let button = UIButton()
button.addTarget(self, action: #selector(buttonAction(sender:otherParams:)), for: .touchUpInside)

@objc func buttonAction(sender: UIButton, otherParams: [String : Any]) {
    print("buttonAction")
}

相关文章

  • oc Swift 混编

    oc Swift 混编 oc 项目 混编Swift1.1 oc 调用 Swift 的类 和 方法步骤: ...

  • OC和Swift混编二

    Swift工程下混编 OC工程下混编请查看OC和Swift混编一 1.建一个Swift工程命名为SwiftTest...

  • Swift(总)

    Swift目录如下: Objective-C和Swift混编指南-s混编-OC&Swift[https://www...

  • OC和Swift混编一

    OC工程下混编 Swift工程下混编请查看OC和Swift混编二 1.建一个OC工程命名为OCTestSwift ...

  • OC和Swift混编手动创建桥接文件及命名空间

    Obj-C混编Swift && Swift混编Obj-C Swift引用OC实现通过桥接头文件,OC引用Swift...

  • Swift

    混编 15、OC与Swift的混编_海森堡_lichangan的博客-CSDN博客_oc swift 混编[htt...

  • OC Swift文件混编

    一.Swift 类可以继承 OC 类,OC 类不能继承 Swift 类。 二.Swift 和 OC 混编 三.两个...

  • OC和Swift混编

    OC和Swift的混编,分为两种情况: OC项目中嵌入Swift文件 Swift项目中嵌入OC文件 先来看OC项目...

  • Swift 和 OC 混编之 framework

    Swift 和 OC 混编之 framework 在主工程为 Swift 的 framework 中引用 OC 代...

  • swift与OC混编

    swift与OC混编的总结 现在的swift开发多数会用到混编。swift和oc是通过桥接文件来实现的。无论是在o...

网友评论

      本文标题:【Swift】:OC和Swift混编

      本文链接:https://www.haomeiwen.com/subject/douhactx.html