副标题:为什么这段代码有效?它似乎允许通过某种强制来比较NSNumber
和NSString
类型。我正在尝试将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上呆了几个月,但这看起来很奇怪。
答案 0 :(得分:8)
好的,让我们一步一步地完成这一步。
首先,_persData
中的所有元素都是字符串。期。 NSString
是一个类集群,因此您查询的各种实例的具体类可能看起来很奇怪,但这是为了支持免费桥接以及与此讨论无关的其他魔法。
NSNumber *currMax = [pD objectAtIndex:1];
此行不正确。您可能会认为存在某种强制行为,但实际上您只是将NSString *
分配给NSNumber *
。这是错的,并且会在最方便的时候在你的脸上爆炸。碰巧objectAtIndex:
返回一个id
,它被删除了类型信息,所以编译器信任你将它存储在正确的指针类型中,但是在你尝试发送一个指针之前不会强制执行消息给它。
if (SS1 >= currMax) SS1 = currMax;
这是一个非常狡猾的比较。 SS1
肯定是NSNumber
,但currMax
是NSString
。但我们并没有比较这些对象的价值。为此,我们使用compare:
方法。相反,我们将它们作为指针进行比较,仅查看它们在内存中的地址。由于某些实施意外,SS1
似乎总是位于比currMax
更高的地址。
如果上述所有情况都属实,那么在执行上述行之后,SS1
始终为NSString
类型,这就解释了为什么这一行:
NSLog(@"%@", [SS1 class]);
始终表示SS1
是一个字符串。
答案 1 :(得分:2)
您实际上使用NSMutableArray
初始化NSString
,而不是数字。
当您使用NSMutableArray
从objectAtIndex
中提取对象时,该函数的返回类型为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);