21.7 Objective-C调用Swift实现的计算器

在上一节我们实现了Swift调用Objective-C,现在我们再来介绍一下Objective-C调用Swift实现。

21.7.1 在Objective-C工程中添加Swift类

如果我们已经有一个使用Objective-C语言编写的工程,还需要调用其他Swift类实现某些功能,那就可以充分利用Swift编写的代码。

下面我们具体在Objective-C版计算器工程中添加Swift的CalcLogic类。右键选择Calculator组,选择菜单中的“New File…”弹出新建文件模板对话框。如图21-39所示,选择iOS→Source→Cocoa Touch Class。

{%}

图 21-39 选择文件模板

接着单击“Next”按钮,随即出现如图21-40所示的界面。在Class中输入“CalcLogic”,Subclass of(继承自)项目选择NSObject,在Language中选择Swift,其他的项目保持默认值就可以了。

{%}

图 21-40 新建Swift类

设置完相关选项后,单击“Next”按钮,进入保存文件界面,根据提示选择存放文件的位置,然后单击“Create”按钮创建Swift类。

21.7.2 调用代码

从Objective-C调用Swift不需要桥接头文件。在Objective-C端,视图控制器ViewController的代码基本上不需要修改,但是要想访问Swift对象还是需要引入一个头文件,这个文件的命名是 <工程名>-Swift.h,那么就需要在ViewController.h文件中引入头文件,ViewController.h代码如下:

  1. #import <UIKit/UIKit.h>
  2. #import "Calculator-Swift.h" ①
  3. @interface ViewController : UIViewController
  4. {
  5. CalcLogic logic;
  6. }
  7. @property (weak, nonatomic) IBOutlet UILabel mainLabel;
  8. - (IBAction)operandPressed:(id)sender;
  9. - (IBAction)equalsPressed:(id)sender;
  10. - (IBAction)clearPressed:(id)sender;
  11. - (IBAction)decimalPressed:(id)sender;
  12. - (IBAction)numberButtonPressed:(id)sender;
  13. @end

上述代码第①行引入了头文件Calculator-Swift.h,这样Objective-C就可以访问工程中的Swift类了。

此外,还需要修改一下Swift端的代码,Swift端的CalcLogic.swift代码如下:

  1. import Foundation
  2. enum Operator : Int {
  3. case Plus = 200, Minus, Multiply, Divide
  4. case Default = 0
  5. }
  6. @objc class CalcLogic : NSObject {
  7. //保存上一次的值
  8. var lastRetainValue : Double
  9. //最近一次选择的操作符(加、减、乘、除)
  10. var opr : Operator
  11. //临时保存MainLabel内容,为true时,输入数字MainLabel内容被清为0
  12. var isMainLabelTextTemporary : Bool
  13. /*
  14. * 构造器
  15. override init () { ②
  16. println("CalcLogic init")
  17. lastRetainValue = 0.0
  18. isMainLabelTextTemporary = false
  19. opr = .Default
  20. }
  21. * 析构器
  22. deinit {
  23. println("CalcLogic deinit")
  24. }
  25. 判断字符串中是否包含.
  26. /
  27. func updateMainLabelStringByNumberTag(tag : Int, withMainLabelString
  28. mainLabelString : String)->String {
  29. var string = mainLabelString
  30. if (isMainLabelTextTemporary) {
  31. string = “0”
  32. isMainLabelTextTemporary = false
  33. }
  34. let optNumber = tag - 100
  35. //把String转为double
  36. var mainLabelDouble = (string as NSString).doubleValue
  37. if mainLabelDouble == 0 && doesStringContainDecimal(string) == false {
  38. return String(optNumber)
  39. }
  40. let resultString = string + String(optNumber)
  41. return resultString
  42. }
  43. /*
  44. * 判断字符串中是否包含小数点
  45. func doesStringContainDecimal(string : String)->Bool {
  46. for ch in string {
  47. if ch == "." {
  48. return true
  49. }
  50. }
  51. return false
  52. }
  53. 点击操作符时的计算
  54. /
  55. func calculateByTag(tag : Int, withMainLabelString mainLabelString : String)->String {
  56. //把String转为double
  57. var currentValue = (mainLabelString as NSString).doubleValue
  58. switch Operator {
  59. case .Plus:
  60. lastRetainValue += currentValue
  61. case .Minus:
  62. lastRetainValue -= currentValue
  63. case .Multiply:
  64. lastRetainValue *= currentValue
  65. case .Divide:
  66. if currentValue != 0 {
  67. lastRetainValue = currentValue
  68. } else {
  69. opr = .Default
  70. isMainLabelTextTemporary = true
  71. return "错误"
  72. }
  73. Default:
  74. lastRetainValue = currentValue
  75. }
  76. /记录当前操作符,下次计算时使用
  77. opr = Operator(rawValue:tag)!
  78. let resultString = NSString(format: "%g", lastRetainValue)
  79. isMainLabelTextTemporary = true
  80. return resultString
  81. }
  82. func clear() {
  83. lastRetainValue = 0.0
  84. isMainLabelTextTemporary = false
  85. opr = .Default
  86. }
  87. }

上述代码与纯Swift版本变化不是很大。但是需要注意代码第①行,CalcLogic类继承了NSObject类,而纯Swift版本中的CalcLogic类是没有继承任何父类的。再有我们在类前面声明为@objc,这也是与纯Swift版本的区别,@objc所声明的类能够被Objective-C访问,@objc还可以修饰属性。代码第②行override init()是重写NSObject父类构造器init()

代码编写完成后,我们可以运行一下看看效果。