Swift&Objective-C混編互調

Swift開發是一種大趨勢了,每一年Apple都會發布新的版本。可是它的第三方庫仍是沒有Objective-C的多,並且想用老項目中的工具類或框架,該怎麼辦呢?swift

這就須要Swift&Objective-C混編互調了,可是在Objective-C的編譯器主要能夠識別如下幾種擴展名的文件:bash

  • .m文件,能夠編寫Objective-C代碼或者C語言代碼;
  • .cpp文件,C++文件,只能識別C++或者C語言代碼;
  • .mm,主要用於編寫C++和Objective-C混編的代碼,能夠同時識別Objective-C、C和C++代碼。

那麼該怎麼讓Swift&Objective-C混編互調呢?在Apple發佈Swift的時候已經提供了方案,在iOS8之後Apple給出了這兩種語言之間的橋接方案,簡單來講就是在Swift工程中,經過提示建立的Bridging頭文件能夠將Objective-C文件和Swift文件銜接在一塊兒,從而能夠在Objective-C文件中引用Swift類,或者在Swift文件中引用Objective-C的類。框架

下面咱們一塊兒來具體操做一下:ide

1. 建立一個Swift工程,選擇Single View App
2. 先新建一個swift類

新建類SwiftObjct.swift,包含一個屬性,一個實例方法,一個類方法:工具

import UIKit

class SwiftObjct: NSObject
{
    var name = "swiftObject"
    
    func instanceMethod( ) -> Void
    {
        print("swift instance method")
    }
    
    class func classMethod( ) -> Void
    {
        print("swift class method")
    }
}
複製代碼
3. 建立第一個OC類時會提示建立一個bridging header文件

會自動生成一個頭文件 SwiftObjectiveC-Bridging-Header.h(前綴是工程名)學習

再建立一個Objective-C類OCObject,一樣包含一個屬性,一個實例方法,一個類方法:ui

#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類調用Objective-C的類

在工程自動生成的類ViewController.swift中調用咱們剛建立的Objective-C的類OCObjectatom

import UIKit
class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        let ocObject = OCObject();
        ocObject.instanceMethod()
        OCObject.classMethod()   
    }
}
複製代碼

此時編譯器會報錯Use of unresolved identifier 'OCObject',緣由是咱們尚未把Objective-C的類和Swift關聯起來。在建立第一個Objective-C類OCObject的時候生成的頭文件SwiftObjectiveC-Bridging-Header.h,就是鏈接它們的橋樑。spa

在頭文件中導入剛建立的Objective-C類OCObject:翻譯

#import "OCObject.h"

複製代碼

而後必定要command+B編譯經過一下,此時ViewController.swift調用的OCObject就再也不報錯了。

5. Objective-C類調用Swift類

上一步創建的鏈接以後,接下來咱們在OCObject.m實現它的兩個方法,並調用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");
}
複製代碼

此時還會報錯Use of undeclared identifier 'SwiftObjct',這個地方就還須要導入一個新的文件:

// 名字前綴是工程名
#import "SwiftObjectiveC-Swift.h"

複製代碼

你會發現,在工程中搜不到此頭文件,這是由於這個類時隱藏的,工程自動生成的,它的做用就是對工程中全部swift類文件進行了向Objective-C語言的翻譯。因此導入這個頭文件以後,上面的代碼就不會報剛纔的錯了。可是又報新的錯誤了,SwiftObjct類是識別了,可是不識別它的方法和屬性:

這是由於Swift4.0之後,暴露給Objective-C類調用的swift方法和屬性都要在前面加上修飾詞:@objc,不然Objective-C類沒法找到對應的Swift方法和屬性。另外須要注意定義後必定要command+B編譯經過一下工程,才能正常在Objective-C文件中調用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編譯事後,報錯都沒有了,並正常打印:

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
複製代碼
注意:

一、Swift類中不須要import頭文件,由於它們的做用域是全局的;
二、SwiftObjectiveC-Swift.h文件是隱藏的,它對工程中全部swift類文件進行了向Objective-C語言的翻譯;
三、修改Swift類後必定要command+B編譯經過一下。

歡迎加入iOS開發交流學習羣,咱們一塊兒共同窗習,共同成長

相關文章
相關標籤/搜索