iOS 开发:Object-C 数字对象入门

4 阅读2分钟

在 Objective-C 中,数字处理主要分为两类:基本 C 语言类型(如 int, float)和对象类型(如 NSNumber, NSDecimalNumber)。

由于 Objective-C 的集合类(如 NSArray, NSDictionary)只能存储对象,不能直接存储基本类型,因此掌握如何将数字“对象化”是开发的关键。


1. 核心概念:基本类型 vs 对象类型

类型例子存储位置集合支持
基本类型 (Scalar)int, double, BOOL, NSInteger栈内存不支持直接存入数组/字典
对象类型 (Object)NSNumber, NSDecimalNumber堆内存完美支持

2. NSNumber:最常用的数字包装器

NSNumber 可以包装所有的标准 C 语言数字类型。

快速语法(语法糖)

现代 Objective-C 推荐使用 @ 符号快速创建对象:

NSNumber *intObj = @10;            // 整数
NSNumber *floatObj = @3.14f;       // 浮点数
NSNumber *doubleObj = @3.14159;    // 双精度
NSNumber *boolObj = @YES;          // 布尔值
NSNumber *charObj = @'A';          // 字符

3. 学习代码案例

下面的代码展示了如何创建数字对象、在数组中使用它们,以及如何转回基本类型。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // 1. 创建 NSNumber 对象 (使用字面量语法)
        NSNumber *myInt = @42;
        NSNumber *myDouble = @3.14159;
        NSNumber *myBool = @YES;

        // 2. 将对象放入数组 (基本类型 int 做不到这一点)
        NSArray *numberArray = @[myInt, myDouble, myBool];
        NSLog(@"数组内容: %@", numberArray);

        // 3. 从对象中提取基本类型 (Unboxing)
        int i = [myInt intValue];
        double d = [myDouble doubleValue];
        BOOL b = [myBool boolValue];

        NSLog(@"还原后的值: %d, %f, %d", i, d, b);

        // 4. 数字比较
        NSNumber *numA = @100;
        NSNumber *numB = @200;

        if ([numA compare:numB] == NSOrderedAscending) {
            NSLog(@"numA 小于 numB");
        }

        // 5. 判断相等
        if ([numA isEqualToNumber:@100]) {
            NSLog(@"值相等");
        }
    }
    return 0;
}

4. NSDecimalNumber:高精度计算(金融必备)

如果你在开发电商或金融应用,绝对不能用 floatdouble,因为它们存在浮点数精度丢失问题。此时要用 NSDecimalNumber

// 计算 0.1 + 0.2
NSDecimalNumber *num1 = [NSDecimalNumber decimalNumberWithString:@"0.1"];
NSDecimalNumber *num2 = [NSDecimalNumber decimalNumberWithString:@"0.2"];

// 加法运算
NSDecimalNumber *sum = [num1 decimalNumberByAdding:num2];

NSLog(@"精确计算结果: %@", sum); // 输出 0.3,而不会是 0.300000000004

5. NSValue:包装结构体

NSNumberNSValue 的子类。NSValue 可以包装更复杂的 C 结构体(如坐标、范围)。

// 包装常见的 UIKit/CoreGraphics 结构体 (iOS 开发常用)
// CGPoint p = {10, 20};
// NSValue *pointValue = [NSValue valueWithCGPoint:p]; 

// 通用包装 (自定义结构体)
typedef struct { int rank; int score; } PlayerStats;
PlayerStats s = {1, 100};
NSValue *statValue = [NSValue valueWithBytes:&s objCType:@encode(PlayerStats)];

6. 开发者避坑指南(重点)

  1. 不要用 == 比较 NSNumber 对象
    • numA == numB 比较的是内存地址。
    • 必须使用 [numA isEqualToNumber:numB]compare:
  2. NSInteger 不是对象
    • NSInteger 只是 intlong 的别名。它依然是基本类型。只有 NSNumber 才是对象。
  3. 不可变性
    • NSNumber 对象一旦创建,值就不能更改。如果需要改变,必须创建一个新的对象。

总结:学习路径

  1. 初学者:先掌握 @10 这种写法,学会如何把数字存进 NSArray
  2. 进阶:理解 intValue, doubleValue 等转换方法。
  3. 实战:在涉及钱的计算时,强制自己使用 NSDecimalNumber