Swift開發(fā)是一種大趨勢了,每年Apple都會發(fā)布新的版本。但是它的第三方庫還是沒有Objective-C的多,而且想用老項(xiàng)目中的工具類或框架,該怎么辦呢?
這就需要Swift&Objective-C混編互調(diào)了,但是在Objective-C的編譯器主要可以識別以下幾種擴(kuò)展名的文件:
- .m文件,可以編寫Objective-C代碼或者C語言代碼;
- .cpp文件,C++文件,只能識別C++或者C語言代碼;
- .mm,主要用于編寫C++和Objective-C混編的代碼,可以同時(shí)識別Objective-C、C和C++代碼。
那么該怎么讓Swift&Objective-C混編互調(diào)呢?在Apple發(fā)布Swift的時(shí)候已經(jīng)提供了方案,在iOS8以后Apple給出了這兩種語言之間的橋接方案,簡單來說就是在Swift工程中,通過提示創(chuàng)建的Bridging頭文件可以將Objective-C文件和Swift文件銜接在一起,從而可以在Objective-C文件中引用Swift類,或者在Swift文件中引用Objective-C的類。
下面我們一起來具體操作一下:
1. 創(chuàng)建一個(gè)Swift工程,選擇Single View App

2. 先新建一個(gè)swift類
新建類SwiftObjct.swift,包含一個(gè)屬性,一個(gè)實(shí)例方法,一個(gè)類方法:
import UIKit
class SwiftObjct: NSObject
{
var name = "swiftObject"
func instanceMethod( ) -> Void
{
print("swift instance method")
}
class func classMethod( ) -> Void
{
print("swift class method")
}
}
3. 創(chuàng)建第一個(gè)OC類時(shí)會提示創(chuàng)建一個(gè)bridging header文件

會自動生成一個(gè)頭文件 SwiftObjectiveC-Bridging-Header.h(前綴是工程名)
再創(chuàng)建一個(gè)Objective-C類OCObject,同樣包含一個(gè)屬性,一個(gè)實(shí)例方法,一個(gè)類方法:
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface OCObject : NSObject
@property (nonatomic,strong) NSString *name;
-(void)instanceMethod;
+(void)classMethod;
@end
NS_ASSUME_NONNULL_END
4. Swift類調(diào)用Objective-C的類
在工程自動生成的類ViewController.swift中調(diào)用我們剛創(chuàng)建的Objective-C的類OCObject
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let ocObject = OCObject();
ocObject.instanceMethod()
OCObject.classMethod()
}
}
此時(shí)編譯器會報(bào)錯(cuò)Use of unresolved identifier 'OCObject',原因是我們還沒有把Objective-C的類和Swift關(guān)聯(lián)起來。在創(chuàng)建第一個(gè)Objective-C類OCObject的時(shí)候生成的頭文件SwiftObjectiveC-Bridging-Header.h,就是連接它們的橋梁。
在頭文件中導(dǎo)入剛創(chuàng)建的Objective-C類OCObject:
#import "OCObject.h"
然后一定要command+B編譯通過一下,此時(shí)ViewController.swift調(diào)用的OCObject就不再報(bào)錯(cuò)了。
5. Objective-C類調(diào)用Swift類
上一步建立的連接之后,接下來我們在OCObject.m實(shí)現(xiàn)它的兩個(gè)方法,并調(diào)用SwiftObjct:
-(void)instanceMethod
{
SwiftObjct *swiftObject = [[SwiftObjct alloc] init];
[swiftObject instanceMethod];
NSLog(@"oc instance method, swiftObjct.name=%@", swiftObject.name);
}
+(void)classMethod
{
[SwiftObjct classMethod];
NSLog(@"oc class method");
}
此時(shí)還會報(bào)錯(cuò)Use of undeclared identifier 'SwiftObjct',這個(gè)地方就還需要導(dǎo)入一個(gè)新的文件:
// 名字前綴是工程名
#import "SwiftObjectiveC-Swift.h"
你會發(fā)現(xiàn),在工程中搜不到此頭文件,這是因?yàn)檫@個(gè)類時(shí)隱藏的,工程自動生成的,它的作用就是對工程中所有swift類文件進(jìn)行了向Objective-C語言的翻譯。所以導(dǎo)入這個(gè)頭文件之后,上面的代碼就不會報(bào)剛才的錯(cuò)了。但是又報(bào)新的錯(cuò)誤了,SwiftObjct類是識別了,但是不識別它的方法和屬性:

這是因?yàn)镾wift4.0以后,暴露給Objective-C類調(diào)用的swift方法和屬性都要在前面加上修飾詞:@objc,否則Objective-C類無法找到對應(yīng)的Swift方法和屬性。另外需要注意定義后一定要command+B編譯通過一下工程,才能正常在Objective-C文件中調(diào)用swift屬性和方法。
所以對SwiftObjct.swift修改如下:
import UIKit
class SwiftObjct: NSObject
{
@objc var name = "swiftObject"
@objc func instanceMethod( ) -> Void
{
print("swift instance method")
}
@objc class func classMethod( ) -> Void
{
print("swift class method")
}
}
然后command+B編譯過后,報(bào)錯(cuò)都沒有了,并正常打印:
swift instance method
2019-08-12 18:06:09.617260+0800 SwiftObjectiveC[19281:400024] oc instance method, swiftObjct.name=swiftObject
swift class method
2019-08-12 18:06:09.617474+0800 SwiftObjectiveC[19281:400024] oc class method
注意:
1、Swift類中不需要import頭文件,因?yàn)樗鼈兊淖饔糜蚴侨值模?br>
2、SwiftObjectiveC-Swift.h文件是隱藏的,它對工程中所有swift類文件進(jìn)行了向Objective-C語言的翻譯;
3、修改Swift類后一定要command+B編譯通過一下。