我在Objective-C中开发了几年,但从未遇到过类似的事情。我想知道是否有人解释为什么这样做是可能的,请看:
NSNumber *number = [NSNumber numberWithDouble:1.23413];
NSDictionary *dicTest = @{ @"number": number };
NSString *string = [dicTest valueForKey:@"number"];
NSLog(@"Is string? %d", [string isKindOfClass:[NSString class]]);
NSLog(@"Is number? %d", [string isKindOfClass:[NSNumber class]]);
调试器说变量的类型是:
string __NSCFNumber * (double)1.23413 0x000060c000222ae0
在运行时如何实现而不会崩溃?不是要输入 objective-c 吗?
最佳答案
Objective-C不会以您期望的方式强烈执行类型。valueForKey:
的返回类型为id
,表示“对象标识符”。 id
类型可以引用任何类的实例,并且可以在不进行任何检查的情况下转换为指向任何特定类的指针。除非将无法识别的消息发送到实例,否则不会出错。例如,此语句:
NSLog(@"length = %ld", (long)string.length);
触发此运行时错误:
-[__NSCFNumber length]: unrecognized selector sent to instance 0x100404230
您有时可以使用“轻量级泛型”来强制进行更强的键入。但是,您首先需要了解,通常不应该使用
valueForKey:
。 valueForKey:
消息是``键值编码''(KVC)的一部分,是一种在运行时按名称访问对象属性的方法。您应该在字典上使用objectForKey:
([dicTest objectForKey:@"number"]
)或直接使用下标(dicTest[@"number"]
)。好的,假设您修改了方法,改用
objectForKey
。然后,如果字典中的所有值都是NSNumber *
,则可以这样声明字典:NSDictionary<NSString *, NSNumber *> *dicTest = @{ @"number": number };
如果您假设从字典中提取的值的类型不同,则会收到警告:
NSString *string = [dicTest objectForKey:@"number"];
// warning: incompatible pointer types initializing 'NSString *' with an expression of type 'NSNumber * _Nullable' [-Wincompatible-pointer-types]
关于ios - 为什么我可以将NSNumber放在NSString中而不得到异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51773467/