優雅的開發 Swift 和 Objective-C 混編的 Framework

WeldonPoind 7年前發布 | 42K 次閱讀 Swift Apple Swift開發 Objective-C

前言

為什么要寫這樣一篇文章,因為昨天和一個朋友討論到Swift和Objective C如何混合開發Framework,中途發現了很多有意思的坑。

用Swift封裝OC的庫是一件比較常見的事情,畢竟對于大多數公司來說,老的代碼都是用OC寫的,而且經過多次迭代,這些OC的代碼已經被驗證了是穩定的,用Swift重寫代價太大。這就引入了一個需求:

  • 用Swift和OC來混編一個Framework。

如果你之前沒有用Swift和Objective C混合開發,建議看看這篇文檔:

這篇文檔很詳細的講解了如何運用Objective C和Swift進行混合開發App和Framework。于是,我們先按照文檔來寫一個混編的Framework

按照文檔一步一步來

新建一個基于單頁面工程,然后新建一個一個Target,選中Cocoa Touch Framework。然后,分別新建一個Swift文件和Objective C類,注意Target Member Ship選中Framework。類的內容如下:

OCSource.h

#import <span class="hljs-title"><Foundation/Foundation.h></span>
 
@interface OCSource : NSObject

  • (void)functionFromOC; @end   </code></pre>

    OCSource.m

    #import "OCSource.h"
     
    @implementationOCSource
     
  • (void)functionFromOC{     NSLog(@"%@",@"Log from objective c in framework"); } @end     </code></pre>

    Swift調用OC

    新建SwiftSource.swift

    open class SwiftIt{
        public init(){}
        letocObject = OCSource()
        public funcencapsulate(){
            ocObject.functionFromOC()
        }
    }
    

    然后,按照文檔中, 為了讓Swift文件訪問Objective C文件 ,我們應該在umbrella header,也就是 MixFramework.h 中,暴露所需要的header。

    也就是, MixFramework.h ,

    #import <MixFramework/OCSource.h>
    

    然后,自信滿滿的點擊build。

    Boom~~~,編譯不通過。

    原因:OCSource.h默認編譯的時候是Project權限. 為了在umbrella header中使用,要把這個文件的權限改成Public

    按照圖中的方式拖過去即可。

    嗯,現在build,可以看到build成功了。

    OC調用Swift

    在SwiftSource.swift中,增加一個類,

    openclass ClassForOC:NSObject{
        public static lettextForOC = "textForOC"
    }
    

    然后,為了在OC中調用Swift的方法,我們需要導入頭文件,這時候,OCSource.m文件內容如下

    #import "OCSource.h"
    #import <MixFramework/MixFramework-Swift.h>
     
    @implementation OCSource
     
  • (void)functionFromOC{     NSLog(@"%@",[ClassForOC textForOC]); } @end </code></pre>

    然后,build,發現成功了,很開心。

    外部調用

    在ViewController.swift中,我們調用Framework中的內容。

    importMixFramework
    class ViewController: UIViewController {
        var t = SwiftIt()
        overridefuncviewDidLoad() {
            super.viewDidLoad()
            t.encapsulate()
            // Do any additional setup after loading the view, typically from a nib.
        }
     
        overridefuncdidReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    }
     
    

    然后運行,發現控制臺打印出

    2017-03-02 16:08:24.000 HostApplication[19524:167669] textForOC
    

    嗯,framework打包成功了。

    問題

    通常,我們希望暴露給外部的接口是 純Swift,而OC文件的具體接口應該隱藏 ,這就是我標題中的優雅兩個字的含義。

    如果你好奇,你會發現,在ViewController.swift中你可以這么調用

        var s = OCSource()
    

    也就是說,OC的內容也暴露出來了, 這破壞了Framework的封裝特性

    通過查看MixFramework的編譯結果,發現最后暴露出的接口是這樣子的

    importFoundation
    importMixFramework.OCSource
    importMixFramework
    importMixFramework.Swift
    importSwiftOnoneSupport
    importUIKit
     
    //
    //  MixFramework.h
    //  MixFramework
    //
    //  Created by Leo on 2017/3/2.
    //  Copyright ? 2017年 Leo Huang. All rights reserved.
    //
     
    //! Project version number for MixFramework.
    public var MixFrameworkVersionNumber: Double
    openclass ClassForOC : NSObject {
     
        public static lettextForOC: String
    }
     
    open class SwiftIt {
     
        public init()
     
        public funcencapsulate()
    }
     
     
    

    這一行,把OC對應的實現暴露出來了

    importMixFramework.OCSource
    

    優雅的解決方案

    不再通過umbrella header的方式讓framework中的Swift調用OC方法。而是通過 modulemap

    新建一個 module.modulemap 文件,內容如下

    module OCSource [system] {
        //由于module.modulemap和OCSource.h是在同一個文件夾的,如果不是同一個,路徑要寫全
        header "OCSource.h"
        export *
    }
    

    這里的#(SRCROOT)是XCode的宏,會自動替換成項目所在的根目錄,這里輸入的路徑是module.modulemap文件所在的路徑。

    然后,刪除 MixFramework.h (umbrella header)中#import 的OC header。

    把OCSource.h的權限改回默認的project。

    再編譯,發現OC的類被隱藏了。

    總結

    如果你要開發一個framework,一定要想清楚哪些接口暴露出去,哪些封裝起來,framework不是簡單把一包文件加個殼子。

     

    來自:http://ios.jobbole.com/93115/

     

 本文由用戶 WeldonPoind 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!