NSNumber 是 Swift 中 Foundation 框架提供的一个类,用于封装基本数值类型(如 Int、Float、Double、Bool 等),以提供一种统一的接口来处理不同类型的数值数据。它最早设计用于 Objective-C,但在 Swift 中仍然非常有用,尤其是在与动态类型或者 Cocoa 框架交互时。
基本特点
1、多类型支持:
NSNumber 能封装几乎所有的基本数值类型,如 Int、Float、Double、Bool、UInt 等。
可以使用 NSNumber 的实例访问这些封装的值。
2、不可变:
NSNumber 的实例是不可变的,意味着其值在创建后不能更改。
3、与 Objective-C 的桥接:
在与 Objective-C 的 API 交互时,NSNumber 是一个关键的桥接类型,用于将数值类型转换为通用对象。
创建 NSNumber
1、使用基本数值类型
import Foundation
let numberFromInt = NSNumber(value: 42) // Int
let numberFromDouble = NSNumber(value: 3.14) // Double
let numberFromBool = NSNumber(value: true) // Bool
2、从字符串或其他输入创建
可以通过 NSDecimalNumber(NSNumber 的子类)从字符串构建精确的数值:
let decimalNumber = NSDecimalNumber(string: "123.456")
print(decimalNumber) // 输出 123.456
获取封装的值
NSNumber 提供方法将值提取为各种类型:
let number = NSNumber(value: 42.5)
let intValue = number.intValue // 转为 Int,结果 42
let doubleValue = number.doubleValue // 转为 Double,结果 42.5
let boolValue = number.boolValue // 转为 Bool,非零值为 true
NSNumber 的用途
1、作为动态数值容器
可以在运行时决定存储哪种数值类型:
func printNumber(_ number: NSNumber) {
print("Double: \(number.doubleValue), Int: \(number.intValue)")
}
printNumber(NSNumber(value: 42)) // 输出 Double: 42.0, Int: 42
printNumber(NSNumber(value: 3.14)) // 输出 Double: 3.14, Int: 3
2、与 Objective-C API 交互
在使用一些 Cocoa 框架(如 UserDefaults、Core Data、NotificationCenter)时,NSNumber 是常用类型:
let defaults = UserDefaults.standard
defaults.set(NSNumber(value: 42), forKey: "integerKey")
if let savedNumber = defaults.object(forKey: "integerKey") as? NSNumber {
print(savedNumber.intValue) // 输出 42
}
3、存储混合数据类型
NSNumber 可以存储混合类型的数值在集合中:
let mixedArray: [NSNumber] = [
NSNumber(value: 42),
NSNumber(value: 3.14),
NSNumber(value: true)
]
for number in mixedArray {
print(number) // 输出 42, 3.14, 1
}
4、与动态类型的桥接
NSNumber 支持在 Swift 和 Objective-C 中动态检查类型:
let number = NSNumber(value: 42.5)
if let isInteger = number as? Int {
print("It's an integer: \(isInteger)")
} else {
print("Not an integer") // 会输出这句
}
注意事项
1、精度问题:
尽量使用 NSDecimalNumber 处理高精度的数值计算。
将浮点类型提取为整数时会进行截断:
let number = NSNumber(value: 42.9)
print(number.intValue) // 输出 42
2、动态类型的风险:
如果使用 NSNumber 包装动态类型,可能需要进行类型检查或转换,避免崩溃。
3、与 Swift 强类型的对比:
Swift 本身的 Double、Int 等类型更高效、更安全。
NSNumber 适用于需要动态行为或与 Objective-C 桥接的场景。
总结
NSNumber 是一个灵活的工具,可以在动态环境中处理数值数据,同时也在与 Objective-C API 的交互中发挥重要作用。尽管 Swift 的类型系统更安全和强大,NSNumber 仍然是某些场景下的首选类型。