Mixing Swift & ObjectiveC

零、 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:
[[EaseMob sharedInstance].chatManager asyncRegisterNewAccount:@"8001" password:@"111111"
    withCompletion:^(NSString *username, NSString *password, EMError *error) {
    if (!error) {
        NSLog(@"注册成功");
    }
} onQueue:nil];
翻译成 Swift 闭包是这样的:
EaseMob.sharedInstance().chatManager.asyncRegisterNewAccount(userName, password: password,
    withCompletion: {userName, password, error in
    if error == nil {
        println("注册成功")
    }
}, onQueue: nil)

2. enum 问题

用 Objective-C 定义了如此的 enum:
typedef enum : NSUInteger {
    EMErrorServerNotReachable,
    EMErrorServerTimeout,
    EMErrorServerAuthenticationFailure,
}  EMErrorType;
比如我在调用注册代码以后,需要判断错误类型,根据错误种类做出相应的措施,用 Objective-C 判断是这样的:
switch (error.errorCode) {
    case EMErrorServerNotReachable:
    // Do something
        break;
    case EMErrorServerAuthenticationFailure:
    // Do something
        break;
    case EMErrorServerTimeout:
    // Do something
        break;
    default: break;
}
然而用 Swift 做 Switch 操作需要这样:
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,有一个设置用户自动登录的方法:
// 设置自动登录
[[EaseMob sharedInstance].chatManager setIsAutoLoginEnabled:YES];
我在 Swift 文件中不管怎样写都实现不了这段代码。我的解决方案是,新建一个 Objective-C 的类,其中一个类方法为:
+ (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

© Xinyu 2014 - 2024