本文介绍了普通的NSDictionary为什么不警告我有关错误键入的密钥插入/分配的信息?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么以下 NSDictionary / NSMutableDictionary 调用不会产生错误或警告?

Why don't the following NSDictionary/NSMutableDictionary calls produce an error or warning?

我希望在这里出现错误,因为rhs NSDictionary 文字与 NSDictionary lhs局部变量的通用类型不匹配.

I expect an error here because the rhs NSDictionary literal doesn't match the generic types of the NSDictionary lhs local variable.

NSDictionary<NSString *, NSNumber *> *foo = @{ @(42) : @"foo" };

我期望在这里出现错误,因为密钥类型与 NSMutableDictionary 的密钥通用类型不匹配:

I expect an error here because the key type doesn't match the NSMutableDictionary's key generic type:

NSMutableDictionary<NSString *, NSNumber *> *foo = [NSMutableDictionary new];
// neither of these calls produces an error. :(
foo[@(42)] = @(42);
[foo setObject:@(42) forKey:@(42)];

当我尝试分配一个不正确类型的值时,我看到一个错误,所以我知道泛型错误在起作用:

I see an error when I try to assign an improperly-typed value, so I know generics errors are working somewhat:

NSMutableDictionary<NSString *, NSNumber *> *foo = [NSMutableDictionary new];
foo[@"foo"] = @"bar";

引起以下警告:

Foo.m:81:16: Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber * _Nullable'

为什么原义赋值或键入不正确的键不会引起警告/错误?

Why don't literal assignment or improperly-typed keys cause warnings/errors?

我将其归档为雷达.

推荐答案

似乎这是编译器的一个限制/错误,由 setObject:forKeyedSubscript:方法的定义引起:

Seems this is a limitation/bug of the compiler, caused by the definition of the setObject:forKeyedSubscript: method:

- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key;

符合协议的要求某种程度上隐藏了 KeyType 的类型要求.如果不存在< NSCopying> ,则编译器将进行 KeyType 检查并警告您.

The protocol conforming requirement somehow hides the type requirement for KeyType. If <NSCopying> is not present, then the compiler makes the KeyType check and warns you.

为确认这一点,我使用了一些代码,结果如下:

To confirm this, I played with some code, here are the results:

@interface MyDictionary<KeyType, ObjectType>: NSObject    
- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType <NSCopying>)key;
@end

...

MyDictionary<NSNumber*, NSNumber*>* dict = [[MyDictionary alloc] init];
UIButton *button = [[UIButton alloc] initWithFrame:CGRectZero];
dict[@"98"] = @14; // no warnings
dict[button] = @14; //warning: Sending 'UIButton *' to parameter of incompatible type 'id<NSCopying>'

上面的代码具有与 NSMutableDictionary 相同的行为.但是,如果我删除了 KeyType < NSCopying> 协议一致性限制,则编译器会给出相应的警告:

The above code has the same behaviour as NSMutableDictionary. However, if I remove the <NSCopying> protocol conformance restriction for KeyType, then the compiler gives the appropriate warning:

@interface MyDictionary<KeyType, ObjectType>: NSObject
- (void)setObject:(nullable ObjectType)obj forKeyedSubscript:(KeyType)key;
@end

...

MyDictionary<NSNumber*, NSNumber*>* dict = [[MyDictionary alloc] init];
dict[@"98"] = @14; // warning: Incompatible pointer types sending 'NSString *' to parameter of type 'NSNumber *'

注意.默认情况下,您会收到有关对象类型不匹配的警告,如果您想接收错误,则可以启用将所有警告视为错误构建设置,或仅将 Treat不兼容的指针类型警告作为错误之一.

Note. By default you'll get warnings for object types mismatch, if you want to receive errors, you can either enable the Treat all warnings as errors build setting, or just the Treat Incompatible Pointer Type Warnings as Errors one.

这篇关于普通的NSDictionary为什么不警告我有关错误键入的密钥插入/分配的信息?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-24 21:53