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

Bry*_*son 1 objective-c ios

副标题:为什么这段代码有效?它似乎允许通过某种强制来NSNumberNSString类型进行比较.我正在尝试将a中的选择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"]);

}
Run Code Online (Sandbox Code Playgroud)

我特别询问:

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

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

         _persData = [[NSMutableArray alloc] initWithObjects:@"2", @"8", @"TWL", @"0", @"0", nil];
Run Code Online (Sandbox Code Playgroud)

这是元素1的一个字符串.那么为什么我可以问它一个NSNumber,它报告它实际上是__NSCFString我可以进行算术比较的?我只是在目标-c几个月,但这似乎很奇怪.

war*_*enm 8

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

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

NSNumber *currMax = [pD objectAtIndex:1];
Run Code Online (Sandbox Code Playgroud)

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

if (SS1 >= currMax) SS1 = currMax;
Run Code Online (Sandbox Code Playgroud)

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

如果以上所有都是真的,那么在执行上面的行后SS1总是类型NSString,这解释了为什么这一行:

NSLog(@"%@", [SS1 class]);
Run Code Online (Sandbox Code Playgroud)

始终表示该SS1字符串.

  • 为了"在最方便的时候在你的脸上爆炸"+1. (3认同)