1.从Swift中调用已有的Objective-C代码
在写了一些独立的Swift组件并对它们进行单元测试后,我们开始用Swift调用已有的Objective-C的类。一切都开始变得实际起来。
要从Swift调用Objective-C的类你需要定义Swift桥接头文件。这是一个.h文件,用来定义所有能暴露给Swift调用的Objective-C头文件。在文件的开头,需要修改编译设置来让编译器在编译的时候把它加进去。当这一切完成后,这些Objective-C的类就被导入进Swift的世界,能被Swift很方便地调用。
当你在Swift中调用Objective-C类时,你可能会收到一个警告:pointer is missing a nullability type specifier。当Objective-C代码被导入到Swift,编译器会检查nullability compatibility--如果没有任何关于nullability的信息,这个提示就会出现。要做这个检查是因为在Swift中nullability信息都是显式申明的,不论是非空类型还是可选类型。
我们唯一需要做的仅仅是在被调用的Objective C头文件中加入nullability信息来消除这些编译器警告。我们使用新的nullable和nonnull标注来达成这一目的。重置工作仅仅只需要花几个小时,因为我们只需要修改我们在Swift中用到的类,无非是几百行的代码。然而,做这些修改时我们绞尽脑汁思考在已有代码库中哪些可以或不能被设置成nil,但当我们把这些代码暴露给Swift时我们无法避免的要做出一个明确的抉择。
在大部分情况下,重构涉及到一些像这样的修改:
1
2
3
4
5
|
// 在.h文件中原来的方法签名
@property (nonatomic, strong, readonly) THSession *session;
// 新的,Swift友好型的方法签名
@property (nonatomic, strong, readonly, nullable) THSession *session;
|
在方法签名中存在block时,修改会略微复杂,但是没有不可掌控的:
1
2
3
4
5
|
// 在.h文件中原来的方法签名
- (NSURLSessionDataTask *)updateWithSuccess: (void(^)())success error:( void(^)(NSError * error))error;
// 新的,Swift友好型的方法签名
- (nonnull NSURLSessionDataTask *)updateWithSuccess: (nullable void(^)())success error:(nullable void(^)(nonnull NSError *error))error;
|
2.在Objective C调用Swift代码
在有不少复杂度适中的使用了Objective-C类的Swift组件后,是时候在Objective C里面调用这些组件了。从Objective-C中调用Swift组件更直接,因为不需要额外的桥接头文件。
唯一需要对现有Swift文件做修改的是继承NSObject或给我们希望暴露的Swift类添加@objc属性。有一些特殊的Swift类Objective-C无法使用,像结构体(structures),元组(tuples),和泛型(generics),以及一些其他的类。这些限制不会造成什么影响,因为我们不想把任何新的结构暴露给Objective-C。唯一我们需要做些额外处理的特例是枚举类型。要使用Swift中定义的枚举类型,需要在Swift中明确申明Int值类型:
1
2
3
|
@objc enum FlightCabinClass: Int {
case
Economy = 1, PremiumEconomy, Business, First, PrivateJet
}
|