Number and Value Programming Topics

这是一个关于C基本数值类型的封装类 NSValue及亲儿子NSNumber, NSDecimalNumber, 和隔壁NSnull的故事

官方原文链接:Number and Value Programming Topics

NSValue:

    NSValue 可以用来装任何标量数值(如int, float, char, 指针, 结构体, object ids)让基本的数值类型可以被添加到Cocoa Foundation 框架中的集合或者数组里面去. NSValue 都是 immutable 的.

    创建 NSValue 使用

NSValue *theValue = [NSValue valueWithBytes: &myRange objCType:@encode(NSRange)];

    需要传递数值型变量的指针及其 encode 类型 ,其中那个"@encode"返回值参看这里

  例子:

NSRange myRange = {4, 10};
NSValue *theValue = [NSValue valueWithBytes: &myRange objCType:@encode(NSRange)];

    创建结构体的 NSValue:

//假设 ImaginaryNumber 已定义;
typedef struct {
    float real;
    float imaginary;
} ImaginaryNumber;
  
ImaginaryNumber miNumber;
miNumber.real = 1.1;
miNumber.imaginary = 1.41;
  
NSValue *miValue = [NSValue valueWithBytes: &miNumber
                              withObjCType:@encode(ImaginaryNumber)];
                              
ImaginaryNumber miNumber2;
[miValue getValue:&miNumber2];

文中还特别举例说明了不要忘记是传指针而不是具体变量数值:

/* INCORRECT! */
char *myCString = "This is a string.";
NSValue *theValue = [NSValue valueWithBytes:myCString withObjCType:@encode(char
*)];

/* Correct. */
char *myCString = "This is a string.";
NSValue *theValue = [NSValue valueWithBytes:&myCString withObjCType:@encode(char
**)];


NSNumber:

可以用来装char, short int,int, NSInteger, long int, long long int, float,  doubleBOOL


还夹带了很多简单好用的初始化方法,如:

NSInteger nine = 9;
float ten = 10.0;
NSNumber *nineFromInteger = [NSNumber alloc] initWithInteger:nine];
NSNumber *tenFromFloat = [NSNumber numberWithFloat:ten];
NSNumber *nineFromInteger = @9;
NSNumber *tenFromFloat = @10.0;
NSNumber *nineteenFromExpression = @(nine + ten);

提供 compare 方法:

NSComparisonResult comparison = [nineFromInteger compare:tenFromFloat];
// comparison = NSOrderedAscending
                    
float aFloat = [nineFromInteger floatValue];
// aFloat = 9.0
BOOL ok = [tenFromFloat boolValue];
// ok = YES

还有就是如果使用了不恰当的类型来保存数值的话将会出错:

NSNumber *bigNumber = @(FLT_MAX);
NSInteger badInteger = [bigNumber integerValue];
NSLog(@"bigNumber: %@; badInteger: %d", bigNumber, badInteger);
// output: "bigNumber: 3.402823e+38; badInteger: 0"


NSDecimalNumber

浮点类型,精度38位,取值大小10底-128到127

-NSDecimalNumberBehaviors protocol

这货是用来处理计算时候发生的逻辑错误的(例如除零)

一些计算方法

NSDecimalAdd
NSDecimalCompact
NSDecimalCompare
NSDecimalCopy
NSDecimalDivide
NSDecimalIsNotANumber
NSDecimalMultiply
NSDecimalMultiplyByPowerOf10
NSDecimalNormalize
NSDecimalPower
NSDecimalRound
NSDecimalString
NSDecimalSubtract

PS: 如果不需要把浮点型当成 obj 处理的话最好还是用 C 原型就可以,速度更加快还比较方便.



NSNull

其实 NSNull 放在这里和前面的 NSValue 没有什么关系的, 不知道为啥就合并在一个 topic 里面了

NSValue 可以在不能使用 nil 的地方使用,例如 array 的元素:

NSNull *nullValue = [NSNull null];
NSArray *arrayWithNull = @[nullValue];
NSLog(@"arrayWithNull:%@",arrayWithNull);
//output: 2015-06-08 17:05:45.081 XYZPersonTest[733:36678] arrayWithNull:("<null>")

NSNull 和 nil 语义上差不多但是实际上不对等:

id aValue = [arrayWithNull objectAtIndex:0];
if (aValue == nil){
    NSLog(@"equals nil");
}else if (aValue == [NSNull null]){
    NSLog(@"equals NSNull instance");
    if ([aValue isEqual:nil]){
        NSLog(@"isEqual:nil");
    }
}
//output: 2015-06-08 17:11:35.376 XYZPersonTest[744:38324] equals NSNull instance


标签:ios, object-c, nsnumber