一、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")
}
网友评论