If am having trouble understanding the following. Consider the following code:
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];
The instructions with image2 and image4 work as expected. The line with image3 on the other hand displays an issue,
Incompatible pointer types initializing 'UIImage *' with an expression of type 'CIImage *'
I understand not type-casting the object retrieved from NSMutableArray
might cause a problem. However, I have a hard time understanding why the compiler would think this expression to be of type CIImage
.
If this question has been asked in more general terms, I apologize, I couldn't find it...
Let's pull this apart:
UIImage *image3 = [[array objectAtIndex:0] image];
Just look at this part:
[array objectAtIndex:0]
Objective-C has no type information for the object returned from this method call, so it types it as an id
. Now you are asking to send the image
message to an id
. But an id
is not a typed object. What is Objective-C to make of this?
Basically, it has to guess what message you are sending. So it looks thru its known repertory of image
methods, and just picks one. It knows of six such methods:
You meant the fourth one. But it happens that the compiler picks the first one, which returns a CIImage. So by your standards, it guessed "wrong". But you made it guess, and it had to guess something.
This is exactly the problem that the cast in your last example fixes:
UIImage *image4 = [(UIImageView *) [array objectAtIndex:0] image];
So, the moral: don't do what you did in the image3
line. Do what you did in the image4
line! You have type information that the compiler doesn't have: tell the compiler what you know.
(Observe that no harm is actually done by the way you wrote the code. The compiler warning is just that: a warning. In actual fact, when the image
message is sent to the UIImageView, a UIImage will be returned and all will be well. But the compiler is warning you that it doesn't know this. By not casting you have given up all static typing and forced the compiler to take its hands off. The compiler doesn't know what will happen, so it warns you that this will have to be resolved at runtime. When you cast, you resolve the matter at compile time.)