iOS (OC与Swift)混编之各种填坑,(实战demo赠送)
iOS混编,大概意思是Objective-C(后面简称OC)工程里面会用到用Swift写的代码文件,或者是Swift工程里面用到用OC写的代码文件;大概分为以下几种情况
- OC工程直接拖入使用.swift文件
- OC工程pod 引入Swift第三方库文件
- Swift工程里面直接拖入使用OC,.h/.m文件
- Swfit工程里面pod 引入OC第三方库文件
OC工程直接拖入使用.swift文件
先给结论:
一 需要把swift文件里面的struct,改为类,并且继承自NSObject
二 在类文件中需要加@objc 或者@objcMembers
三 swift文件里面如果有枚举类型,能转为OC代码的前提是:
- 1.加@objc,同上面;
- 2.枚举的原始值类型是Int型,并且不能有相关值,因为OC里面的枚举只有Int类型,而且没有相关值的概念。
- 3.swift里面枚举类型不能为可选型,因为OC里面的枚举不可以为空
第一步
在OC工程,当拖入第 一swift文件,或者新建第一个swift文件时,会弹出一个创建桥接头文件的窗口,这个需要选择“create Briging Header”,后面我们会用这个头文件

桥接文件的格式 “XXX-Bridging-Header.h”,其中“XXX”是工程的名称,如下图所示

第二步

如上图所示,先来看一下我们的swift文件,里面是一个结构体Person
,在OC里面是没有结构体,只有类的概念,所以正常swift里面的结构体是不能自动转为OC里面的类的,所以应该不会有任何反应的
我们在ViewController里面导入#import "XXX-Swift.h"
,XXX
同样是工程名称,如下图

编译,看一下,导入一个swift文件后,OC工程会不会报错,幸运的是不会编译报错。这个时候尝试敲一个Person
这个类名,看编译器会不会给出提示

结果是没有任何提示,也就说明了结构体,是不能自动转化为OC相应代码
那我们能不能尝试加@objc,让其能转化呢? **(加@objc,是让swift代码能自动转化为OC代码的主要方法)**

如上图所示,直接提示,@objc,应该用在类身上。所以一个小小的结论:
Swift里面的结构体是不能转为OC代码,也就不能在OC工程里面使用的
第三步
我们把Person
改为类的形式,如下所示,然后在ViewController里面看有没有提示

如上图,还是没有任何提示;
那我们再加@objc,而且根据提示,
Person
类要继承NSObject类,再来看看编译器会不会给我们提示
可以看出是可行的,
Person
类已经可以被编译器自动提示出来了。这个时候那些没有加@objc的属性和方法还是不能用的,所以我们得去全部加@objc;
在加@objc之前,我们先按住“Command”键和"OCDemo-Swift.h",跳进去看一下

里面已经根据swift里面的代码,生成对应的OC代码了,目前只有一个init方法;与上面说法
这个时候那些没有加@objc的属性和方法还是不能用的
;是相符的;
好了,我们赶紧全部加上@objc,再来看一下,ViewController界面有没有提示,同时也再进"OCDemo-Swift.h",里面去看看,会不会生成更多的代码;如下所示,确实如我们所想

如果我们类中的属性和方法很多怎么办,也需要这么麻烦一个一个加@objc么,这个时候,我们可以使用一个更高级的关键词@objcMembers
,加上它后,就相当于,所以属性和方法都加了@objc,如下

上面已经验证了结论一,结论二,现在我们来验证结论三,swift中的枚举
我们先在Persion.swift文件里面增加枚举,Cmd+B编译一下,没有报错,但此时还没有加@objc

当我们加@objc后,就直接报错,需要integer类型

我们就按报错的提示来进行修改,结果如下

OC工程pod 引入Swift第三方库文件
结论跟前面一样,使用步骤稍有不同:
一 需要把swift文件里面的struct,改为类,并且继承自NSObject
二 在类文件中需要加@objc 或者@objcMembers
三 swift文件里面如果有枚举类型,能转为OC代码的前提是:
- 1.加@objc,同上面;
- 2.枚举的原始值类型是Int型,并且不能有相关值,因为OC里面的枚举只有Int类型,而且没有相关值的概念。
- 3.swift里面枚举类型不能为可选型,因为OC里面的枚举不可以为空
我们就拿一个swift库来做演示Charts
,用cocospod的方式安装到工程里面如下图所示

使用步骤:
在桥接文件里面导入Charts模块
@import Charts;
(导入过程可能没有代码提示)
在使用的地方,导入桥接文件#import "OCDemo-Bridging-Header.h"
,其中OCDemo
是项目工程的名称

然后就可以看到当敲部分chartView代码,编译器就能把各种头文件提示出来,就可以正常使用这个swift库了
Swift工程里面直接拖入使用OC,.h/.m文件
直接拖入一个Student
类
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Student : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) double score;
-(void)learn;
@end
NS_ASSUME_NONNULL_END
#import "Student.h"
@implementation Student
- (NSString *)name {
return self.name;
}
- (void)setName:(NSString *)name {
self.name = name;
}
- (double)score {
return self.score;
}
- (void)setScore:(double)score {
self.score = score;
}
- (void)learn {
NSLog(@"learn");
}
@end

需要做的,就是在桥接文件SwiftDemo-Bridging-Header.h
里面,导入OC的类
#import "Student.h"

然后就可以在使用的地方,用起来

Swfit工程里面pod 引入OC第三方库文件
我们先Pod一个纯OC库pod 'SVProgressHUD'
,
然后步骤同上,先在桥接文件中 导入OC头文件,然后直接使用OC的类,如下图所示

实践案例
在OC工程里面处理以下几种情况
- OC ViewController里调用自定义OC类
- OC ViewController里调用Pod进来OC类
- OC ViewController里面调用自定义Swift类
- OC ViewController里面调用Pod进来Swift类
- Swift ViewController里调用自定义OC类
- Swift ViewController里调用Pod进来OC类
- Swift ViewController里面调用自定义Swift类
- Swift ViewController里面调用Pod进来Swift类
有经验的小伙伴,应该会想到为什么有以上的这么种情况,比如:一个OC ViewController 会push到一个Swift ViewController,然后Swift ViewController 又push到下一级OC ViewController;这样的混编场景是可能遇到的,就会遇到上面的8种情况。只有处理好上面的8种情况,才算真正意义上实现了混编。
OC文件使用其他文件的导入方式,处理1~4的情况;如下图

Swift文件使用其他文件的导入方式,处理5~8的情况;如下图
在桥接文件需要如下的导入方式,这个是重点,这个是重点,这个是重点
(这个好像其他博主,都没有提到。),在这里导入后,其他swift文件就可以直接使用 桥接文件导入OC文件和swift文件


实战demo放在某盘,有需要的小伙伴自取吧
链接: https://pan.baidu.com/s/18dlFqBsl3iCRzhF0CmGHfw 提取码: rwtf
Github地址请点击这里
结尾
今天的分享至此接近尾声喽,小伴们,觉得有点用的话,或者已经看到这里面来的请点赞加关注吧~~ 后续分享更多iOS原生技术及物联网技术相关文章。如果有疑问的话,欢迎在下方留言~