iOS是否将NSStrings强制转换为NSNumbers?

时间:2012-06-26 01:26:39

标签: objective-c ios

副标题:为什么这段代码有效?它似乎允许通过某种强制来比较NSNumberNSString类型。我正在尝试将UISegmentedControl中的选择与先前存储的值进行比较。

- (IBAction)minSegmentedControlChanged:(id)sender // MINIMUM value
{
UISegmentedControl *s1 = (UISegmentedControl *)sender;

NSMutableArray *pD = [[GameData gameData].curData valueForKey:@"persData"];

// Must make sure max >= min

NSNumber *currMax = [pD objectAtIndex:1];
NSLog(@"%@", [currMax class]); // __NSCFString ?!

int ss1 = s1.selectedSegmentIndex;
NSNumber *SS1 = [NSNumber numberWithInt:ss1 + 2];

if (SS1 >= currMax) SS1 = currMax;

NSLog(@"%@", SS1); // Answer is correct, appears to be an integer
NSLog(@"%@", [SS1 class]); // __NSCFString ?!

[pD replaceObjectAtIndex:0
              withObject:SS1];
[[GameData gameData].curData setObject:pD
                                forKey:@"persData"];
NSLog(@"%@", [[GameData gameData].curData valueForKey:@"persData"]);

}

我特别询问:

NSNumber *currMax = [pD objectAtIndex:1];
NSLog(@"%@", [currMax class]); // __NSCFString ?!

似乎返回一个数字的字符串。 [[GameData gameData].curData valueForKey:@"persData"];初始化如下:

         _persData = [[NSMutableArray alloc] initWithObjects:@"2", @"8", @"TWL", @"0", @"0", nil];

这是元素1的字符串。那么我为什么要问NSNumber,它报告它实际上是__NSCFString,我可以在其上进行算术比较?我只是在目标c上呆了几个月,但这看起来很奇怪。

2 个答案:

答案 0 :(得分:8)

好的,让我们一步一步地完成这一步。

首先,_persData中的所有元素都是字符串。期。 NSString是一个类集群,因此您查询的各种实例的具体类可能看起来很奇怪,但这是为了支持免费桥接以及与此讨论无关的其他魔法。

NSNumber *currMax = [pD objectAtIndex:1];

此行不正确。您可能会认为存在某种强制行为,但实际上您只是将NSString *分配给NSNumber *。这是错的,并且会在最方便的时候在你的脸上爆炸。碰巧objectAtIndex:返回一个id,它被删除了类型信息,所以编译器信任你将它存储在正确的指针类型中,但是在你尝试发送一个指针之前不会强制执行消息给它。

if (SS1 >= currMax) SS1 = currMax;

这是一个非常狡猾的比较。 SS1肯定是NSNumber,但currMaxNSString。但我们并没有比较这些对象的价值。为此,我们使用compare:方法。相反,我们将它们作为指针进行比较,仅查看它们在内存中的地址。由于某些实施意外,SS1似乎总是位于比currMax更高的地址。

如果上述所有情况都属实,那么在执行上述行之后,SS1始终为NSString类型,这就解释了为什么这一行:

NSLog(@"%@", [SS1 class]);

始终表示SS1是一个字符串。

答案 1 :(得分:2)

您实际上使用NSMutableArray初始化NSString,而不是数字。

当您使用NSMutableArrayobjectAtIndex中提取对象时,该函数的返回类型为id,它将盲目地转换为NSNumber,而实际对象是NSString

似乎SS1 >= currMax语句正在比较对象的地址而不是它们的值。

您可以使用以下代码段进行测试:

NSNumber *a = [[NSNumber alloc] initWithUnsignedInt: 34];
NSNumber *b = [[NSNumber alloc] initWithUnsignedInt: 3];

NSNumber *c = [[NSNumber alloc] initWithUnsignedInt: 34];
NSNumber *d = [[NSNumber alloc] initWithUnsignedInt: 234];

NSLog(@"%p %p %p %p %d %d", a, b, c, d, a >= b, c >= d);