概述
- 老项目是 OC 语言实现了,引用了 Swift 框架。
- 新项目是 Swift 实现的,引用了 OC 框架,目前微信 SDK,支付宝 SDK 等都是 OC 实现 所以还需要学习一些相关知识。
如何实现
- 通过官方提供桥接文件这种机制实现。
兼容性
- 不论是 OC 项目调用 Swift,还是反过来都无法使用所有语法。
- 例如:OC 项目调用 Swift,无法使用 Swift 的泛型,枚举,结构体等。
- 反过来,Swift 项目调用 OC,无法使用 OC 的宏定义,指针等。
- 但是,可以使用桥接文件,将 OC 的头文件引入到 Swift 项目中,这样就可以使用 OC 的所有语法了。
- 但是,如果是 Swift 项目调用 OC,OC 项目调用 Swift,都可以使用桥接文件,但是,OC 项目调用 Swift,无法使用 Swift 的泛型,枚举,结构体等。
OC 调用 Swift
创建
Swift
文件,类继承NSObject
,方法和字段前面加@objc
,如果不加OC
中无法调用,但编译不报错。创建桥接文件,第一次创建 Swift 文件时,会提示是否创建桥接文件,可以点击自动创建;又可以稍后手动创建,手动创建,还要开启在
target-Build Settings-All
中,找到Defines Module
,设置为Yes
;同样在Swift
项目中第一次创建OC
文件时也会提示。在要使用
Swift
类的文件中调入自动生成的Swift
兼容文件,和桥接文件。Swift 文件
// 目的是测试在OC中调用这个类的方法和字段
// 一个Swift如果要在OC中使用,必须继承NSObject
// 其他内容(方法,字段)如果要在OC中使用,前面必须加@objc
// 注意:更改完代码,一定要要编译,OC那边才能引用
import Foundation
class TestSwiftObject: NSObject {
@objc var var1 = "这是变量1"
@objc let let1:String = "这是常量"
@objc static let staticLet:String = "这是静态常量"
/// 静态计算属性
@objc open class var staticComputer1: String {
get{
let result = 18*10
return "这是静态的计算属性\(result)"
}
}
/// 静态计算属性
@objc open var computer1: String {
get{
let result = 20*12
return "这是计算属性\(result)"
}
}
/// 懒加载字段
@objc lazy var lazyField1: String = {
let result = 20*12
print("TestSwiftObject lazyField1 这里的逻辑只会执行一次")
return "这是懒加载字段\(result)"
}()
/// 静态登录方法
/// - Parameters:
/// - name: <#name description#>
/// - age: <#age description#>
/// - Returns: <#description#>
@objc static func login(name:String,age:Int) -> String {
return "TestSwiftObject login \(name) \(age)"
}
/// 静态登录方法,方法的参数名省略了
/// - Parameters:
/// - name: <#name description#>
/// - age: <#age description#>
/// - Returns: <#description#>
@objc static func login2(_ name:String,_ age:Int) -> String {
return "TestSwiftObject login2 \(name) \(age)"
}
/// 登录方法
/// - Parameters:
/// - name: <#name description#>
/// - age: <#age description#>
/// - Returns: <#description#>
@objc func login11(name:String,age:Int) -> String {
return "TestSwiftObject login11 \(name) \(age)"
}
/// 登录方法,方法的参数名省略了
/// - Parameters:
/// - name: <#name description#>
/// - age: <#age description#>
/// - Returns: <#description#>
@objc func login12(_ name:String,_ age:Int) -> String {
return "TestSwiftObject login12 \(name) \(age)"
}
}
- 要使用导入桥接文件
//导入桥接文件
#import "TestOCUseSwift-Bridging-Header.h"
//如果当前项目有Swift文件,需要在targets的Build Settings将Defines Module设置为YES
//然后编译项目,就会自动生成该文件,这个文件在Xcode中看不到,但可以直接引用
//引用以后,才能在当前文件使用当前项目的Swift源码里面的内容
#import "TestOCUseSwift-Swift.h"
- 使用 Swift 类
//-------------方法测试
//调用Swift类中的静态方法
NSString *result = [TestSwiftObject loginWithName:@"这是名称" age:20];
NSLog(@"%@",result);
//Swift类中的静态方法,方法参数名称省略了
result=[TestSwiftObject login2:@"这是名称2" :30];
NSLog(@"%@",result);
//调用Swift类中的实例方法
TestSwiftObject *testObject = [[TestSwiftObject alloc] init];
result = [testObject login11WithName:@"这是名称11" age:11];
NSLog(@"%@",result);
//调用Swift类中的实例方法,方法参数名称省略了
result = [testObject login12:@"这是名称12" :12];
NSLog(@"%@",result);
//-------------字段
NSLog(@"静态常量字段:%@",TestSwiftObject.staticLet);
NSLog(@"常量:%@",testObject.let1);
NSLog(@"变量:%@",testObject.var1);
//-------------计算属性
NSLog(@"静态计算属性:%@",TestSwiftObject.staticComputer1);
NSLog(@"计算属性:%@",testObject.computer1);
//-------------懒加载字段
NSLog(@"懒加载:%@",testObject.lazyField1);
NSLog(@"懒加载:%@",testObject.lazyField1);
- 可以看到能正常调用,像 Swift 中的枚举,结构体就不再演示了,目前是没法使用的,预计以后也不可能兼容。
OC 调用 Swift 第三方框架
通过 Pod 安装 Swift 第三方框架,例如:Charts 框架,他是一个使用 Swift 语言编写的图表框架,他是兼容 OC 调用才能调用,所以并不是所有 Swift 框架都能在 OC 中使用,这一步是正常使用
在桥接文件中导入第三方框架的头文件
//在这个文件导入第三方Swift框架模块
@import Charts;
- 使用: 例如折线图
//显示一个折线图
//设置代理,通过他可以监听一些事件
_chartView.delegate = self;
//要显示的数据,例如:模拟爱学啊1~6月份,收入金额
NSArray *datas = @[@30,@40,@80,@70,@20,@20,@30];
NSMutableArray *array = [NSMutableArray array];
for (int i=0; i<datas.count; i++) {
//创建ChartDataEntry对象并将每个点对应的值与x轴 y轴进行绑定
//x就是月份,y就是值
ChartDataEntry *entry = [[ChartDataEntry alloc] initWithX:i+1 y:[datas[i] intValue]];
[array addObject:entry];
}
//创建一个集合并为这个集合赋值 label的值可为空
LineChartDataSet *set = [[LineChartDataSet alloc] initWithEntries:array label:@"收入金额"];
//创建容器
LineChartData *chartData = [[LineChartData alloc] initWithDataSet:set];
self.chartView.data = chartData;
//以动画的方式绘制折线,动画持续2.5秒
[_chartView animateWithXAxisDuration:2.5];
swift 调用 OC
- 创建 OC 类
// TestObject.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
//普通宏,可以在 Siwft 中访问
#define ICON_WIDTH 1228
//复杂宏
#define SCEREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
//这是一个常量
static NSString \* const ICON_NAME = @"ixuea";
@interface TestObject : NSObject
@property (strong,nonatomic) NSString \*var1;
/// 静态登录方法
/// @param name <#name description#>
/// @param age <#age description#>
+(NSString _)loginWithName:(NSString _)name age:(int)age;
/// 登录方法
/// @param name <#name description#>
/// @param age <#age description#>
-(NSString _)login11WithName:(NSString _)name age:(int)age;
@end
NS_ASSUME_NONNULL_END
// TestObject.m
#import "TestObject.h"
@implementation TestObject
- (instancetype)init{
self = [super init];
if (self) {
_var1 = [NSString stringWithFormat:@"%@ %@",@"这是变量1",ICON_NAME];
}
return self;
}
+ (NSString *)loginWithName:(NSString *)name age:(int)age{
return [NSString stringWithFormat:@"TestObject static loginWithName %@ %d",name,age];
}
- (NSString *)login11WithName:(NSString *)name age:(int)age{
return [NSString stringWithFormat:@"TestObject login11WithName %@ %d",name,age];
}
@end
- 导入头文件,
TestSwiftUseOC-Bridging-Header.h
//导入OC头文件,当前项目的,第三方框架的都要导入
#import "TestObject.h"
- 使用类
//调用OC类中的静态方法
var result=TestObject.login(withName: "这是名称", age: 20)
print(result)
//调用OC类中的实例方法
let testObject = TestObject()
result = testObject.login11(withName: "这是名称11", age: 11)
print(result)
//-------------字段
print("变量:\(testObject.var1)")
print("常量:\(ICON_NAME)")
//-------------宏,只能访问普通的宏,复杂的宏不能访问
print("简单宏:\(ICON_WIDTH)")
//print("访问复杂宏:\(SCEREEN_WIDTH)")
Swift 调用 OC 第三方框架
- 添加依赖: 例如这里使用微信 SDK 作为演示,目前微信 SDK 是 OC 实现了
#微信sdk,OC实现的
#https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html
pod 'WechatOpenSDK'
- 在桥接文件中导入,
TestSwiftUseOC-Bridging-Header.h
//微信SDK
#import <WechatOpenSDK/WXApi.h>
- 使用
WXApi.registerApp("", universalLink: "")