Ry’s Objective-C Tutorial → Data Types---NSNumber

RyPress - Quality Software Tutorials

You’re reading Ry’s Objective-C Tutorial → Data Types

NSNumber

The NSNumber class is a lightweight, object-oriented wrapper around C’s numeric primitives. It’s main job is to store and retrieve primitive values, and it comes with dedicated methods for each data type:

NSNumber *aBool = [NSNumber numberWithBool:NO];
NSNumber *aChar = [NSNumber numberWithChar:'z'];
NSNumber *aUChar = [NSNumber numberWithUnsignedChar:255];
NSNumber *aShort = [NSNumber numberWithShort:32767];
NSNumber *aUShort = [NSNumber numberWithUnsignedShort:65535];
NSNumber *anInt = [NSNumber numberWithInt:2147483647];
NSNumber *aUInt = [NSNumber numberWithUnsignedInt:4294967295];
NSNumber *aLong = [NSNumber numberWithLong:9223372036854775807];
NSNumber *aULong = [NSNumber numberWithUnsignedLong:18446744073709551615];
NSNumber *aFloat = [NSNumber numberWithFloat:26.99f];
NSNumber *aDouble = [NSNumber numberWithDouble:26.99];

NSLog(@"%@", [aBool boolValue] ? @"YES" : @"NO");
NSLog(@"%c", [aChar charValue]);
NSLog(@"%hhu", [aUChar unsignedCharValue]);
NSLog(@"%hi", [aShort shortValue]);
NSLog(@"%hu", [aUShort unsignedShortValue]);
NSLog(@"%i", [anInt intValue]);
NSLog(@"%u", [aUInt unsignedIntValue]);
NSLog(@"%li", [aLong longValue]);
NSLog(@"%lu", [aULong unsignedLongValue]);
NSLog(@"%f", [aFloat floatValue]);
NSLog(@"%f", [aDouble doubleValue]);

It may seem redundant to have an object-oriented version of all the C primitives, but it’s necessary if you want to store numeric values in anNSArrayNSDictionary, or any of the other Foundation Framework collections. These classes require all of their elements to be objects—they do not know how to interact with primitive values. In addition, NSNumber makes it possible to pass numbers to methods like performSelector:withObject:, as discussed in Selectors.

But, aside from the object-oriented interface, there are a few perks to using NSNumber. For one, it provides a straightforward way to convert between primitive data types or get an NSString representation of the value:

NSNumber *anInt = [NSNumber numberWithInt:42];
float asFloat = [anInt floatValue];
NSLog(@"%.2f", asFloat);
NSString *asString = [anInt stringValue];
NSLog(@"%@", asString);

And, like all Objective-C objects, NSNumber can be displayed with the %@format specifier, which means that you can forget about all of the C-style specifiers introduced in the Primitives module. This makes life a tiny bit easier when trying to debug values:

NSNumber *aUChar = [NSNumber numberWithUnsignedChar:255];
NSNumber *anInt = [NSNumber numberWithInt:2147483647];
NSNumber *aFloat = [NSNumber numberWithFloat:26.99f];
NSLog(@"%@", aUChar);
NSLog(@"%@", anInt);
NSLog(@"%@", aFloat);

Numeric Literals

Xcode 4.4 introduced numeric literals, which offer a much more convenient alternative to the above factory methods. The NSNumberversion of BOOL’s, char’s, int’s and double’s can all be created by simply prefixing the corresponding primitive type with the @ symbol; however, unsigned int’s, long’s, and float’s must be appended with the UL, or F modifiers, as shown below.

NSNumber *aBool = @NO;
NSNumber *aChar = @'z';
NSNumber *anInt = @2147483647;
NSNumber *aUInt = @4294967295U;
NSNumber *aLong = @9223372036854775807L;
NSNumber *aFloat = @26.99F;
NSNumber *aDouble = @26.99;

In addition to literal values, it’s possible to box arbitrary C expressions using the @() syntax. This makes it trivial to turn basic arithmetic calculations into NSNumber objects:

double x = 24.0;
NSNumber *result = @(x * .15);
NSLog(@"%.2f", [result doubleValue]);

Immutability

It’s important to understand that NSNumber objects are immutable—it’s not possible to change its associated value after you create it. In this sense, an NSNumber instance acts exactly like a primitive value: When you need a new double value, you create a new literal—you don’t change an existing one.

From a practical standpoint, this means you need to create a newNSNumber object every time you change its value. For example, the following loop increments a counter object by adding to its primitive value, then re-boxing it into a new NSNumber and assigning it to the same variable.

NSNumber *counter = @0;
for (int i=0; i<10; i++) {
    counter = @([counter intValue] + 1);
    NSLog(@"%@", counter);
}

As you could probably imagine, this isn’t the most efficient way to work with numbers. In real applications, you should limit yourself to primitive numeric types for computationally intensive algorithms and wait as long as possible to store the result in an NSNumber container.

Comparing Numbers

While it’s possible to directly compare NSNumber pointers, the isEqualToNumber: method is a much more robust way to check for equality. It guarantees that two values will compare equal, even if they are stored in different objects. For example, the following snippet shows a common case of pointer comparison failure.

NSNumber *anInt = @27;
NSNumber *sameInt = @27U;
// Pointer comparison (fails)
if (anInt == sameInt) {
    NSLog(@"They are the same object");
}
// Value comparison (succeeds)
if ([anInt isEqualToNumber:sameInt]) {
    NSLog(@"They are the same value");
}

If you need to check for inequalities, you can use the related compare:method. Instead of a Boolean value, it returns an NSComparisonResult, which is an enum that defines the relationship between the operands:

Return Value Description
NSOrderedAscendingreceiver < argument
NSOrderedSamereceiver == argument
NSOrderedDescendingreceiver > argument

The following example shows these enumerators in action.

 NSNumber *anInt = @27;
NSNumber *anotherInt = @42;
NSComparisonResult result = [anInt compare:anotherInt];
if (result == NSOrderedAscending) {
    NSLog(@"27 < 42");
} else if (result == NSOrderedSame) {
    NSLog(@"27 == 42");
} else if (result == NSOrderedDescending) {
    NSLog(@"27 > 42");
}

This kind of object-oriented comparison may not be as convenient as the familiar <==, and > operators, but abstracting them into methods affords a lot more flexibility to the Foundation Framework classes.

Mailing List

Sign up for my low-volume mailing list to find out when new content is released. Next up is a comprehensive Swift tutorial planned for late January.

Email Address:

You’ll only receive emails when new tutorials are released, and your contact information will never be shared with third parties. Click here to unsubscribe.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值