ios - 为什么我可以将NSNumber放在NSString中而不得到异常?

标签 ios objective-c xcode types

我在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/

相关文章:

iphone - 如果 friend 在应用程序中的进度还不足以到达 installInvitationHandler 方法,如何处理游戏中心邀请?

ios - 在 Objective-C 中使用 JSON 中的 webService

objective-c - iOS 13 中的 AES 加密 CryptLib 不起作用

unit-testing - XCode 和 SenTestingKit 不输出到编辑器窗口

ios - 我们可以有多个动态链接指向单个应用程序吗?

ios - UIButton UILabel 背景 View 不采用传递的背景颜色

objective-c - 奇怪的 cocoa 虫?

objective-c - 我可以在我的方法中使用 self = nil 吗?

swift - 具有适用于 iOS 和 MacOS 目标的共享 CoreData 的 Xcode 项目

iphone - 如何在 NSNumber 上做数学运算