Swift与Objective-C混编(一)

作者: eaa1d39d22a8 | 来源:发表于2015-12-16 16:35 被阅读12916次

    随着Swift的改进及Swift开源项目剧增,越来越多的Objective-C工程开始使用Swift混编,不管是在基于Swift工程中或者Objective-C工程中,Swift和Objective-C文件都可以无缝结合。本文首先介绍下Swift与Objective-C混编的基础;然后在第二节中,根据我实际项目中,将详细展开Swift和Objective-C混编需要注意的一些细节。

    Swift调用Objective-C

    Swift调用Objective-C文件比较简单。当在Swift工程中新建Objective-C文件或者在Objective-C工程中新建Swift文件时,Xcode会自动提示你是否创建bridging header桥接头文件,点击创建后Xcode会自动为你创建一个桥接头文件。
    如图1-1、1-2所示,在基于Swift的SwiftProject工程中创建一个OCViewController时,Xcode会自动创建一个名为SwiftProject-Bridging-Header.h桥接头文件。

    图1-1. Swift工程中自动提示是否创建桥接头文件 图1-2. Xcode自动创建的Swift-Bridging-Header.h桥接头文件

    当然你也可以在Building Settings中自己设置桥接头文件(一般情况下我们会用系统默认生成的),如图1-3所示:


    图1-3 自定义桥接头文件

    创建好Bridging Header文件后,在Bridging Header文件中即可import需要提供给Swift的Objective-C头文件,Swift即可调用对应的Objective-C文件。
    同时Xcode可以自动生成Objective-C对应的Swift接口。如图1-4所示,OCViewController.h对外提供了一些Public的属性和方法,点击Xcode generated interface后可以看到Objective-C转换为Swift后的Public接口。

    图1-4 Xcode可以自动将Objective-C转换为Swift接口

    Objective-C源代码对应的头文件

    // 宏定义
    #define DefaultHeight 100.f
    
    // 协议
    NS_ASSUME_NONNULL_BEGIN
    @protocol OCViewControllerDelegate <NSObject>
    - (void)detailButtonDidPressed:(id)sender;
    @end
    
    @interface OCViewController : UIViewController
    
    // 属性
    @property (nonatomic, weak) id<OCViewControllerDelegate> delegate;
    @property (nonatomic, strong) NSString *testString;
    @property (nonatomic, strong) NSArray  *testArray;
    @property (nonatomic, strong, nullable) NSArray<NSString *> *testArray2;
    @property (nonatomic, strong) NSNumber *testNumber;
    
    // 方法
    - (void)testMethod1;
    - (BOOL)testMethod2WithParam:(NSString *)aParam;
    - (NSString *)testMethod3WithParam:(NSArray *)aArray;
    - (nullable NSString *)testMethod4WithParam:(nullable NSArray*)aArray;
    @end
    NS_ASSUME_NONNULL_END```
    **转换后对应的Swift interface文件如下**
    ```Swift
    import UIKit
    
    // 宏定义
    public var DefaultHeight: Float { get }
    
    // 协议
    public protocol OCViewControllerDelegate : NSObjectProtocol {
        public func detailButtonDidPressed(sender: AnyObject)
    }
    
    public class OCViewController : UIViewController {
        
        // 属性
        weak public var delegate: OCViewControllerDelegate?
        public var testString: String
        public var testArray: [AnyObject]
        public var testArray2: [String]?
        public var testNumber: NSNumber
        
        // 方法
        public func testMethod1()
        public func testMethod2WithParam(aParam: String) -> Bool
        public func testMethod3WithParam(aArray: [AnyObject]) -> String
        public func testMethod4WithParam(aArray: [AnyObject]?) -> String?
    }```
    Objective-C类、协议、属性、方法、扩展、闭包等所有功能都可以无缝地被转换为Swift接口被Swift文件所调用。**但是还是有些特别需要注意的地方,详细将在第二节中讲到**
    - Objective-C中为了兼容 Swift,新增了三大特性Nullability、Lightweight Generics、__kindof,[详细阅读](http://blog.csdn.net/majiakun1/article/details/46530245) 
    - 构造方法
    - 循环引用 (weak & unowned)
    - 基础类型转换 (String、Array、Int)
    - 可选类型
    - 枚举(NS_OPTIONS)
    - 单例
    - 值类型和引用类型
    - 闭包
    - 判等 (== 、 ===、类型判断)
    - 调用Objective-C第三方类库
    - 更多...
    
    ## Objective-C调用Swift
    Xcode会自动为Project生成头文件以便在Objective-C中调用。
    在Objective-C类中调用Swift,只需要#import "productModuleName-Swift.h"即可调用,Xcode提供的头文件以Swift代码的模块名加上-Swift.h为命名。
    在这个头文件中,将包含Swift提供给Objective-C的所有接口、Appdelegate及自动生成的一些宏定义,如图1-5所示。注意productModuleName-Swift.h在Xcode中是无法搜索查看的,只能从import中点击进去查看。
    
    ![图1-5,Xcode自动生成SwiftProject-Swift.h文件"](http:https://img.haomeiwen.com/i727625/d91c54e4047c87bd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/800)
    在大部分情况下,Objective-C都可以无缝地调用Swift,但是由于Swift相对于Objective-C多了一些新特性,比如泛型、元组、枚举的等,所以Swift暴漏给Objective-C的接口多了一些限制,因此Swift只能暴露在Objective-C中有效的接口。
    
    
    ##Swift与C交互
    有时候我们在Swift中可能需要与C交互(如Core Graphics),Swift对此提供了有效的支持。
    - **原始类型**
    Swift提供了将Swift类型直接映射为C原始类型的“类C风格”类型。这些类型以C开头后跟C原始类型名。例如,bool -> CBool,unsigned long long -> CUnsignedLongLong。
    - **指针类型**
    指针类型需要一些描述信息。例如,const void* -> CConstVoidPointer, void* -> CMutableVoidPointer或者COpaquePointer(两者区别在于用于参数还是函数返回值)。
    指向某一类型的指针
    - **类型化的指针**
    可以用泛型语法CMutableVoidPointer<Type>,例如,Int* -> CMutableVoidPointer<Type>
    
    ##Swift与C++交互
    Objective-C能与C/C++很好的交互,目前Swift对C++的交互不是很好的支持(原因苹果认为C++是个很复杂的语言,与C++的交互性需要考虑很多东西,是件很长远的事情,至少在3.0及3.0版本之前Swift不支持),所以如果有些库需要与C++混编可以考虑用Objective-C作为桥接。
    
    ##观点##
    在同一项目中同时使用Swift和Objective-C混编,意味着可用Swift的新的特性及多编程范式为Objective-C项目增加新的特性或者优化代码结构,也可以同时充分利用Objective-C runtime等一些黑魔法。Swift能够与Objective-C和Cocoa框架和平共处,同时对一些C语言的基础类型保持了兼容,Swift的兼容使得它更加强大和便利。一旦在工程中采用Swift和Objective-C混编,你完全不用担心之前已有的Objective-C代码和框架。
    下节将详细展开Swift和Objective-C混编的一些细节详细展开。

    相关文章

      网友评论

      • 肆意二货:你好,我现在用的是swift,我封装了一个类,这个类继承AFHTTPSessionManager,那么现在我无法复写init方法,会报Must call a designated initianated of the superclass AFHTTPSessionManager错误,如果我不复写,继承AFHTTPSessionManager的方法就无法初始化分配内存了,请问知道怎么解决问题么?
      • cfe544701b6d: :smile: 期待下一节 +1
      • becc84b5c902:期待下一节:smiley:

      本文标题:Swift与Objective-C混编(一)

      本文链接:https://www.haomeiwen.com/subject/istuhttx.html