Objective-c 指点迷津。类型保护

Objective-c pointers magic. Type protection

我有一本字典。 我提取其中一个值如下:

NSString *magicValue= [filterDict valueForKey:[filterDict allKeys][0]];
[SomeClass foo: magicValue];

foo 是:

- (void)foo:(NSString*)magicValue
{
    NSLog("magicValue is string:%@",[magic isKindOfClass:[NSString class]] ? @"YES" : @"NO");
    NSLog("magicValue is number:%@",[magic isKindOfClass:[NSNumber class]] ? @"YES" : @"NO");
}

如果字典值为数字,则 magicValue 将为 NSNumber。所以定义的字符串指针将指向 NSNumber。日志将 return 是用于数字检查。

我从未对此类方法添加保护,以检查 class "magicValue" 是什么。我假设当我定义一个带有字符串参数的方法时,它将是字符串。

我应该开始考虑这种行为并始终添加检查,还是以这种方式将该字典值分配给魔法并使用我的方法的人的错。我需要一些最佳实践建议以及如何处理这个问题。

这个问题可能已经有人回答了,但我不知道如何搜索它。

大多数情况下,您应该知道 class 您在引用什么,或者至少知道您打算引用什么。如果您有意外的 class 可能会导致崩溃,具体取决于您发送给它的消息,您可以调试代码并获得正确的引用。

有时,通常在处理继承时,您需要在运行时而非编译时确定 class。这时候,isKindOfClass: 就可以派上用场了。如果您知道一个值可能是许多 class 中的一个,我会将其提取为 id 然后在最后一刻将其转换为例如

id value = [[NSUserDefaults standardUserDefaults] valueForKey:aKey];
if ([value isKindOfClass:[MyClass class]]) {
    // Do one thing
}
else {
    // Do another
}

简答:没有,如果没有特殊原因,请不要检查。

长答案:

你必须区分两种情况:

一个。使用 id

您有一个 id 类型的变量或 return 值。这是您的示例 -valueForKey:。打字的原因是为了保持方法的通用性。即使在理论上是可能的,但在实践中这种情况下的类型不匹配是非常罕见的,并且在开发过程中很快就会被检测到。出于不同的动机,我在一次 public 演讲中询问了听众 (>200),他们在生产中有多少次出现这样的打字错误。对于所有听众,他们的所有应用程序在所有应用程序版本中都有 1(换句话说:一个!)案例。只需忘记这种风险。是使用静态类型语言(Java、C++、Swift)的开发者的焦虑。

乙。分配错误

如果你没有id类型,这样的技巧还是可以的。 (有时您想这样做。这是动态类型的优势。)有两个子类别:

你可以隐式地做:

NSString *string = [NSNumber numberWithInt:1];

编译器会对此发出警告。所以一切都很好,因为开发人员会看到他的错误。你不必保护他或你的代码。

可以明确地做到这一点:

NSString *string = (NSString*)[NSNumber numberWithInt:1];

在这种情况下,代码可能会中断。但他明确地做到了。如果是错误的,开发者有犯罪能量,你不必保护他免受他自己的伤害。