Objective-C: NSMutableArray returns 意外类型的未转换元素

Objective-C: Uncast element of NSMutableArray returns unexpected type

如果我无法理解以下内容。考虑以下代码:

UIImage *image = [[UIImage alloc] initWithContentsOfFile:@"car.png"];
UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:imageView];

UIImage *image2 = [imageView image];
UIImage *image3 = [[array objectAtIndex:0] image];
UIImage *image4 = [(UIImageView *) [array objectAtIndex:0] image];

image2 和 image4 的指令按预期工作。另一方面,带有 image3 的行显示了一个问题,

Incompatible pointer types initializing 'UIImage *' with an expression of type 'CIImage *'

我知道不对从 NSMutableArray 检索到的对象进行类型转换可能会导致问题。但是,我很难理解为什么编译器会认为这个表达式是 CIImage.

类型

如果这个问题被更笼统地问过,我很抱歉,我找不到...

让我们把它分开:

UIImage *image3 = [[array objectAtIndex:0] image];

只看这部分:

[array objectAtIndex:0] 

Objective-C 没有此方法调用返回的对象的类型信息,因此它将其类型化为 id。现在您要求将 image 消息发送到 id。但是 id 不是类型对象。这是什么Objective-C?

基本上,它必须猜测你发送的是什么消息。因此,它会查看其已知的 image 方法库,然后只选择一个。它知道六种这样的方法:

你说的是第四个。但是碰巧编译器选择了第一个,returns 一个 CIImage。所以按照你的标准,它猜到了 "wrong"。但是你让它猜了,它不得不猜 something.

这正是您上一个示例中的转换所解决的问题:

UIImage *image4 = [(UIImageView *) [array objectAtIndex:0] image];

所以,道德:不要做你在 image3 行中所做的事情。执行您在 image4 行中执行的操作!你有编译器没有的类型信息:告诉编译器你知道什么。

(请注意,您编写代码的方式实际上没有造成任何伤害。编译器警告只是一个警告。实际上,当 image 消息发送到 UIImageView 时,一个UIImage 将被返回,一切都会好起来的。但是编译器警告你它不知道这一点。通过不强制转换,你已经放弃了所有静态类型并迫使编译器放手。编译器不知道会发生什么,因此它会警告您必须在运行时 解决这个问题。当您进行转换时,您会在编译时 解决问题。 )