零、 Into

Apple 已经建议开发者今后不再提交纯 Objective-C 书写的程序。而是提交纯 Swift 或者 Swift 与 Objective-C 混编的程序

在 SDK 还是 Objective-C 的前提下,还是可以使用 Swift 进行开发的。这就涉及到了在 Swift 文件中调用 Objective-C 代码的问题。

关于怎样混编 Swift 和 Objective-C 的代码,Apple 的 iOS Developer Library 的这篇文章讲得要比我清楚地多…

一、步骤

首先,需要建立 .pch 文件,这是桥接文件,用于导入需要调用的 Objective-C 代码的头文件。
然后,需要在工程中设置 Objective-C Bridging Header 这一项。

.pch 文件导入 Objective-C 的头文件以后,就可以愉快地在 Swift 中调用已经写好的 Objective-C 代码了。

StackOverflow 上的这个答案步骤要更加完整一些。

二、我遇到的几个坑

1. Block 语法问题

对于下面这个 Block:

1
2
3
4
5
6
[[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:@"8001" password:@"111111"
withCompletion:^(NSString *username, NSString *password, EMError *error) {
if (!error) {
NSLog(@"注册成功");
}
} onQueue:nil];

翻译成 Swift 闭包是这样的:

1
2
3
4
5
6
EaseMob.sharedInstance().chatManager.asyncRegisterNewAccount(userName, password: password,
withCompletion: {userName, password, error in
if error == nil {
println("注册成功")
}
}, onQueue: nil)

2. enum 问题

用 Objective-C 定义了如此的 enum:

1
2
3
4
5
typedef enum : NSUInteger {
EMErrorServerNotReachable,
EMErrorServerTimeout,
EMErrorServerAuthenticationFailure,
} EMErrorType;

比如我在调用注册代码以后,需要判断错误类型,根据错误种类做出相应的措施,用 Objective-C 判断是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
switch (error.errorCode) {
case EMErrorServerNotReachable:
// Do something
break;
case EMErrorServerAuthenticationFailure:
// Do something
break;
case EMErrorServerTimeout:
// Do something
break;
default: break;
}

然而用 Swift 做 Switch 操作需要这样:

1
2
3
4
5
6
7
8
9
switch error.errorCode.value {
case EMErrorServerNotReachable.value:
// Do something
case EMErrorServerAuthenticationFailure.value:
// Do something
case EMErrorServerTimeout.value:
// Do something
default: break
}

3. BOOL 的 setter 问题

这个问题我也不知道算不算是个问题,原因是什么我也不太了解。

在接触环信 SDK,有一个设置用户自动登录的方法:

1
2
// 设置自动登录
[[EaseMob sharedInstance].chatManager setIsAutoLoginEnabled:YES];

我在 Swift 文件中不管怎样写都实现不了这段代码。我的解决方案是,新建一个 Objective-C 的类,其中一个类方法为:

1
2
3
+ (void)setIsAutoLoginEnabled:(BOOL)flag {
[[EaseMob sharedInstance].chatManager setIsAutoLoginEnabled:flag];
}

这样,我在 Swift 文件中就可以愉快地调用了。

参考资料:

  1. http://stackoverflow.com/questions/24168612/working-with-objective-c-blocks-with-swift
  2. http://stackoverflow.com/questions/24544712/how-do-i-access-an-enum-in-swift-from-objective-c
  3. https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html#//apple_ref/doc/uid/TP40014216-CH4-XID_25
  4. http://stackoverflow.com/questions/24002369/how-to-call-objective-c-code-from-swift