Swift和Objective-C混合编程

1. 首先打开Xcode6,建立一个项目,这里我使用的Objective-C默认的编程语言,项目名字叫 “SwiftAndObjective”。

2. 为了在OC中使用Swift的演示所以需要建立下面的几个类。

  a)建立一个Objective-C的类继承自NSObject,名字叫OCTypeClass, 所以会自动产生两个对应的 .m 和 .h文件,这对熟悉Objective-C的人非常熟悉。

  b)  尽力一个Swift类,名字叫SwiftFile1, 在点击创建的时候,会弹出一个提示问是否创建一个hander .h文件,这里必须选择是。因为如果想要在Swift中使用Objective-C的类的话,这是一个必备文件,具体使用稍后再说。结果会创建一个SwiftFile1.swift文件和一个header文件。

  c)为了描述访问控制符public、private、默认等的关系,需要再创建一个Swift文件,名字叫SwiftFile2,会生成一个SwiftFile2.swift的文件。

好了文件创建部分完毕。


3. 需要定义类(因为swift可以不继承任何类,但是如果需要被Objective-C使用的时候,我们使用的allocnew等创建使用的方法是继承自NSObject的,所以Swift中的这些类,我都继承了NSObject了)。

 在SwiftFile1.swift文件中创建下面的类

import Foundation

@objc public class PublicObjcTypeSwiftClass1: NSObject {
    var property1: Int = 0
}


@objc class ObjcTypeSwiftClass1: NSObject {
    var property1: Int = 0
}

@objc private class ObjcPrivateTypeSwiftClass1: NSObject {
    var property1: Int = 0
}

public class PublicSwiftClass1 : NSObject {
    var property1: Int = 0
}

class SwiftClass1: NSObject {
    var property1: Int = 0
}

private class PrivateSwiftClass1: NSObject {
    var property1: Int = 0
}


在SwiftFile2.swift中创建下面的类

<pre name="code" class="objc">import Foundation

@objc public class PublicObjcTypeSwiftClass2: NSObject {
    var property1: Int = 0
    //var ocClass: OCTypeClass = OCTypeClass()
    
    //func test() {
    //    ocClass.property1 = 0
    //}
}


@objc class ObjcTypeSwiftClass2: NSObject {
    var property1: Int = 0
}

@objc private class ObjcPrivateTypeSwiftClass2: NSObject {
    var property1: Int = 0
}

public class PublicSwiftClass2: NSObject {
    var property1: Int = 0
}

class SwiftClass2: NSObject {
    var property1: Int = 0
}

private class PrivateSwiftClass2: NSObject {
    var property1: Int = 0
}



4. 因为OC文件定义之后会自动生成对应的类,所以无需再次定义了。

#import "OCTypeClass.h"
#import "SwiftAndObjective-Swift.h"

@implementation OCTypeClass

- (void)test
{
    PublicObjcTypeSwiftClass1 *type = [[PublicObjcTypeSwiftClass1 alloc] init];
    type.property1 = 0;
    
    
    ObjcTypeSwiftClass1 *type2 = [[ObjcTypeSwiftClass1 alloc] init];
    type2.property1 = 0;
}

@end


5. 打开OCTypeClass.m 文件我们需要引用Swift文件中的类。可以使用“项目工程名+ ‘-’ + Swfit.h"的形式引入所以的public的并且被标记为@objc的类(标记成@objc的类,即使不显示的写出public标记也会被Objective-C类使用)。下面的具体的代码(注意当写#import “”的使用,目前版本的Xcode不会自动识别需要的Swift的header名字,需要自己手动写,注意:不要写错项目名,如果确认是写对了,但是又一直报错可以去刷新项目,或者重启,重新build: Project-》 Clean, Project-》Build,大不了重新启动Xcode)。


6.  完成后可以通过查看源代码的形式(command + 鼠标左键)的形式查看xcode自动生成的Objective-C类。

// Generated by Swift version 1.1 (swift-600.0.54.20)
#pragma clang diagnostic push

#if defined(__has_include) && __has_include(<swift/objc-prologue.h>)
# include <swift/objc-prologue.h>
#endif

#pragma clang diagnostic ignored "-Wauto-import"
#include <objc/NSObject.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#if defined(__has_include) && __has_include(<uchar.h>)
# include <uchar.h>
#elif !defined(__cplusplus) || __cplusplus < 201103L
typedef uint_least16_t char16_t;
typedef uint_least32_t char32_t;
#endif

typedef struct _NSZone NSZone;

#if !defined(SWIFT_PASTE)
# define SWIFT_PASTE_HELPER(x, y) x##y
# define SWIFT_PASTE(x, y) SWIFT_PASTE_HELPER(x, y)
#endif
#if !defined(SWIFT_METATYPE)
# define SWIFT_METATYPE(X) Class
#endif

#if defined(__has_attribute) && __has_attribute(objc_runtime_name)
# define SWIFT_RUNTIME_NAME(X) __attribute__((objc_runtime_name(X)))
#else
# define SWIFT_RUNTIME_NAME(X)
#endif
#if !defined(SWIFT_CLASS_EXTRA)
# define SWIFT_CLASS_EXTRA
#endif
#if !defined(SWIFT_PROTOCOL_EXTRA)
# define SWIFT_PROTOCOL_EXTRA
#endif
#if !defined(SWIFT_CLASS)
# if defined(__has_attribute) && __has_attribute(objc_subclassing_restricted) 
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) __attribute__((objc_subclassing_restricted)) SWIFT_CLASS_EXTRA
# else
#  define SWIFT_CLASS(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_CLASS_EXTRA
# endif
#endif

#if !defined(SWIFT_PROTOCOL)
# define SWIFT_PROTOCOL(SWIFT_NAME) SWIFT_RUNTIME_NAME(SWIFT_NAME) SWIFT_PROTOCOL_EXTRA
#endif

#if !defined(SWIFT_EXTENSION)
# define SWIFT_EXTENSION(M) SWIFT_PASTE(M##_Swift_, __LINE__)
#endif

#if !defined(OBJC_DESIGNATED_INITIALIZER)
# if defined(__has_attribute) && __has_attribute(objc_designated_initializer)
#  define OBJC_DESIGNATED_INITIALIZER __attribute__((objc_designated_initializer))
# else
#  define OBJC_DESIGNATED_INITIALIZER
# endif
#endif
#if defined(__has_feature) && __has_feature(modules)
@import ObjectiveC;
#endif

#pragma clang diagnostic ignored "-Wproperty-attribute-mismatch"
#pragma clang diagnostic ignored "-Wduplicate-method-arg"

SWIFT_CLASS("_TtC17SwiftAndObjective19ObjcTypeSwiftClass1")
@interface ObjcTypeSwiftClass1 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective19ObjcTypeSwiftClass2")
@interface ObjcTypeSwiftClass2 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective25PublicObjcTypeSwiftClass1")
@interface PublicObjcTypeSwiftClass1 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective25PublicObjcTypeSwiftClass2")
@interface PublicObjcTypeSwiftClass2 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective17PublicSwiftClass1")
@interface PublicSwiftClass1 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective17PublicSwiftClass2")
@interface PublicSwiftClass2 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective11SwiftClass1")
@interface SwiftClass1 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end


SWIFT_CLASS("_TtC17SwiftAndObjective11SwiftClass2")
@interface SwiftClass2 : NSObject
@property (nonatomic) NSInteger property1;
- (instancetype)init OBJC_DESIGNATED_INITIALIZER;
@end

#pragma clang diagnostic pop


7. 下面开始在Swift文件中使用Objective-C的类。

 a)打开xcode自动为我们生成的SwiftAndObjective-Bridging-Header.h文件, 导入暴露给swift的类。

这里为了方便就使用刚刚定义的类,只是为了演示:

#import "OCTypeClass.h"

 b)然后我们什么都不需要做了,直接在Swfit文件中实现吧。

import Foundation

@objc public class PublicObjcTypeSwiftClass2: NSObject {
    var property1: Int = 0
    var ocClass: OCTypeClass = OCTypeClass()
    
    func test() {
        ocClass.property1 = 0
    }
}


@objc class ObjcTypeSwiftClass2: NSObject {
    var property1: Int = 0
}

@objc private class ObjcPrivateTypeSwiftClass2: NSObject {
    var property1: Int = 0
}

public class PublicSwiftClass2: NSObject {
    var property1: Int = 0
}

class SwiftClass2: NSObject {
    var property1: Int = 0
}

private class PrivateSwiftClass2: NSObject {
    var property1: Int = 0
}


注意:

1. 如果想把一个Swfit类暴露给Objective-C的话需要标识@objc

2. 对于private类型的Swift类,只能在所定义的Swift文件中被使用。

3. 在一个Swift文件中的类,只能访问外部Swift文件中定义的public类型的类。


差点忽略了最重要的一点:如果有什么问题或者错误,欢迎指正或者交流。


示例代码: 代码下载地址

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。