標籤:
開發中常見錯誤和警告總結(十六)
Objective-c巧妙調用不相容的Swift方法
在Objective-c中調用Swift類中的方法時,由於部分Swift文法不支援轉換,會遇到無法找到對應方法的情況,如下:
1 import UIKit 2 enum HTTPState { 3 case Succed, Failed, NetworkError, ServerError, Others 4 } 5 class ILHTTPRequest: NSObject { 6 class func requestLogin(userName: String, password: String, callback: (state: HTTPState) -> (Void)) { 7 dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in 8 NSThread.sleepForTimeInterval(3) 9 dispatch_async(dispatch_get_main_queue(), { () -> Void in10 callback(state: HTTPState.Succed)11 })12 })13 }14 }
對應的$(SWIFT_MODULE_NAME)-Swift.h檔案為:
1 SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest")2 @interface ILHTTPRequest : NSObject3 - (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER;4 @end
從上面的標頭檔中可以看出,方法requestLogin使用了不支援的Swift枚舉,轉換時方法被自動忽略掉,有以下兩種辦法,可以巧妙解決類似問題:
用支援的Swift文法封裝
在Swift檔案中,添加一個可相容封裝方法wrapRequestLogin,注意此方法中不能使用不相容的類型或者文法
1 import UIKit 2 enum HTTPState: Int { 3 case Succed = 0, Failed = 1, NetworkError = 2, ServerError = 3, Others = 4 4 } 5 class ILHTTPRequest: NSObject { 6 class func requestLogin(userName: String, password: String, callback: (state: HTTPState) -> (Void)) { 7 dispatch_async(dispatch_get_global_queue(0, 0), { () -> Void in 8 NSThread.sleepForTimeInterval(3) 9 dispatch_async(dispatch_get_main_queue(), { () -> Void in10 callback(state: HTTPState.Succed)11 })12 })13 }14 class func wrapRequestLogin(userName: String, password: String, callback: (state: Int) -> (Void)) {15 self.requestLogin(userName, password: password) { (state) -> (Void) in16 callback(state: state.rawValue)17 }18 }19 }
對應的$(SWIFT_MODULE_NAME)-Swift.h檔案為:
1 SWIFT_CLASS("_TtC12ILSwiftTests13ILHTTPRequest")2 @interface ILHTTPRequest : NSObject3 + (void)wrapRequestLogin:(NSString * __nonnull)userName password:(NSString * __nonnull)password callback:(void (^ __nonnull)(NSInteger))callback;4 - (SWIFT_NULLABILITY(nonnull) instancetype)init OBJC_DESIGNATED_INITIALIZER;5 @end
此時,我們可以在Objective-c中直接使用封裝後的方法wrapRequestLogin
巧妙使用繼承
使用繼承可以支援所有的Swift類型,主要的功能在Objective-c中實現,不支援的文法在Swift檔案中調用,例如,ILLoginSuperController做為父類
1 @interface ILLoginSuperController : UIViewController 2 @property (weak, nonatomic) IBOutlet UITextField *userNameField; 3 @property (weak, nonatomic) IBOutlet UITextField *passwordField; 4 - (IBAction)loginButtonPressed:(id)sender; 5 @end 6 //////////////////////////////////////////////////////////////// 7 @implementation ILLoginSuperController 8 - (IBAction)loginButtonPressed:(id)sender 9 {10 }11 @end
建立Swift檔案,繼承自ILLoginSuperController,在此Swift檔案中調用那些不支援的文法
1 import UIKit2 class ILLoginController: ILLoginSuperController {3 override func loginButtonPressed(sender: AnyObject!) {4 ILHTTPRequest.requestLogin(self.userNameField.text, password: self.passwordField.text) { (state) -> (Void) in5 //具體商務邏輯6 }7 }8 }
iOS開發——錯誤總結篇&開發中常見錯誤和警告總結(十六)