19.1 数字类NSNumber

在Objective-C语言中有一些基本数据类型2:intcharfloatdouble,但是它们都不是类,不具有方法、成员变量和属性以及面向对象的特征。为了实现“一切都是对象”的承诺,因此在Foundation框架中使用NSNumber类来封装这些数字类型。这样数字就具有面向对象的基本特征了。

2基本数据类型intcharfloatdouble事实上是由C语言提供的,它们可以在C、C++和Objective-C中使用。

19.1.1 获得NSNumber实例

不仅是NSNumber类,Foundation框架中几乎所有的类,都有两种获得实例的方式:一种是通过构造器创建,另一种是通过工厂设计模式创建。

如图19-1所示,打开NSNumber的API帮助文档,单击菜单栏中的“显示目录”按钮,在页面的左边显示目录。其中以number开头的方法是静态工厂创建方法,它通过工厂设计模式创建NSNumber对象获得实例;而以init开头的方法构造器,则通过构造器创建NSNumber对象并初始化成员获得实例。

{%}

图 19-1 NSNumber API帮助文档

提示 静态工厂创建方法命名是有规律的,即把类名去掉NS前缀,小写后作为方法的开头,例如NSString的静态工厂创建方法class func stringWithUTF8String(_ bytes: CString) -> Self!。该方法是通过一个UTF8字符串创建NSString字符串对象,它采用的命名方法是使用string开头。

下面看示例代码:

  1. import Foundation
  2. var intSwift = 80
  3. var intNumber1 = NSNumber(integer: intSwift)
  4. var intNumber2 = NSNumber(int: CInt(intSwift))
  5. var floatNumber1 = NSNumber(double: 80.00)
  6. let myint = intNumber1.intValue
  7. let myfloat = floatNumber1.floatValue

使用Foundation框架需要通过第①行的import Foundation语句引入框架。代码第②行、第③行和第④行使用NSNumber构造器创建对象,也就是NSNumber API中的init开头的方法构造器,例如我们打开NSNumber API中-initWithInteger:构造器,如图19-2所示,在Foundation框架中以init开头的方法构造器就是这样的,不同的语言语法表现形式不同。init(integer value: Int)构造器调用时就需要写成NSNumber(integer: intSwift)的形式,integer是外部参数名。

{%}

图 19-2 NSNumber API中-initWithInteger:构造器

代码第③行、第⑥行和第⑦行使用静态工厂创建对象。第⑧行和第⑨代码是调用属性获得基本数据类型数值。

第④行和第⑦行分别使用了CInt()CDouble()函数,它们将数据类型转换为CIntCDouble类型。在Swift中有一些数据类型与Objective-C类型中的基本数据类型相对应。表19-1是Objective-C基本数据类型和Swift类型对应关系表。

表19-1 类型对应关系

Objective-C类型 Swift类型
bool CBool
char, signed char CChar
unsigned char CUnsignedChar
short CShort
unsigned short CUnsignedShort
int CInt
unsigned int CUnsignedInt
long CLong
unsigned long CUnsignedLong
long long CLongLong
unsigned long long CUnsignedLongLong
wchar_t CWideChar
char16_t CChar16
char32_t CChar32
float CFloat
double CDouble

提示 Swift中的转换函数就是该类型加上括号,如CInt类型的转换函数就是CInt()

19.1.2 NSNumber对象的比较

数字的比较是非常常见的操作,那么在比较两个NSNumber对象大小的时候,可以转化成为基本数据类型比较,当然可以使用NSNumber的方法比较,这就是对象的优势了。

与比较相关方法有isEqualToNumbercompare,这两个方法的定义如下:

  1. func isEqualToNumber(_ aNumber: NSNumber!) ->Bool
  2. func compare(_ aNumber: NSNumber!) ->NSComparisonResult

isEqualToNumber只是比较是否相等,而compare方法可以比较是否相等、大于和小于,它的返回值是NSComparisonResult枚举类型。NSComparisonResult枚举类型定义如下:

  1. enum NSComparisonResult : Int {
  2. case OrderedAscending //升序,前一个数比后一个数小
  3. case OrderedSame //两个数相等
  4. case OrderedDescending //降序,前一个数比后一个数大
  5. }

下面看一个示例:

  1. import Foundation
  2. var intSwift = 89
  3. var intNumber = NSNumber(integer: intSwift)
  4. var floatNumber = NSNumber(double: 80.00)
  5. if intNumber.isEqualToNumber(floatNumber) == true {
  6. NSLog("相等")
  7. } else {
  8. NSLog("不相等")
  9. }
  10. switch intNumber.compare(floatNumber) {
  11. case.OrderedAscending:
  12. NSLog("第一个数小于第二个数")
  13. case .OrderedDescending:
  14. NSLog("第一个数大于第二个数")
  15. case .OrderedSame:
  16. NSLog("第一个数等于第二个数")
  17. }

输出结果如下:

  1. 2014-07-05 21:08:10.089 PlaygroundStub_OSX[7052:303] 不相等
  2. 2014-07-05 21:08:10.092 PlaygroundStub_OSX[7052:303] 第一个数大于第二个数

上述代码比较简单,基本不需要解释,但是需要注意的是NSLog函数是Foundation框架中的函数,也可以在Swift中使用,它的用途是日志输出,与Swift的println类似。