Reputation: 6662
I'm using a GitHub repo named MNCalendar, and I wanted to call some cells. Now, here's how I did it.
MNCalendarViewDayCell *cell = [self.collectionView cellForItemAtIndexPath:indexPath];
MNCalendarViewDayCell *cell = (MNCalendarViewDayCell*)[self.collectionView cellForItemAtIndexPath:indexPath];
The first line gave me an issue about it being a MNCalendarViewDayCell pointer to UICollectionViewCell, but the other one was fine. What's going on under the hood here, why is the bottom one correct?
Not critical bug, just an issue, just wondering and trying to learn something from it :)
Upvotes: 3
Views: 155
Reputation: 150785
cellForItemAtIndexPath:
returns a UICollectionViewCell
instance. But you are assigning it to a MKCalendarViewCell variable.
If MKCalendarViewCell is a subclass of UICollectionViewCell, then there isn't really a problem under the Liskov Substitution Principle. And Objective-C is a dynamic language so this is supported.
The error you are seeing comes from the compiler, telling you that you are assigning an object of one type to a variable of the other type. And by casting it you are saying that although the return type is of one class, you know better and that it is actually an instance of another class. This now becomes your problem to verify that this is actually the case.
Upvotes: 1
Reputation: 5376
In both statements your are downcasting a UICollectionViewCell
to MNCalendarViewDayCell
.
Since MNCalendarViewDayCell
is a subclass of UICollectionViewCell
it may implement methods that are not implemented in UICollectionViewCell
, this is why you get the warning. Using (MNCalendarViewDayCell *)
forces the cast and drops the warning.
Upvotes: 0
Reputation: 31304
cellForItemAtIndexPath
returns a pointer to a UICollectionViewCell
object, but you're assigning the result to a MNCalendarViewDayCell
.
The warning is the compiler telling you "hey - this variable you've declared is a MNCalendarViewDayCell
, but it looks like you're assigning an object of a different type to it'.
In this case, this is intentional - you've created a custom sub-class of UICollectionViewCell
. This mis-matched type won't cause any problems. So to prevent the warning we do what's called casting: we tell the compiler even though the method says it will return a pointer to one class we expect it to be another:
MNCalendarViewDayCell *cell = (MNCalendarViewDayCell*)[self.collectionView cellForItemAtIndexPath:indexPath];
Upvotes: 2
Reputation: 13546
cellForItemAtIndexPath
returns you UICollectionViewCell, not your custom MNCalendarViewDayCell. So when you assign result to MNCalendarViewDayCell *cell
, it raises error (According to OOP, parent doesn't know about it's child, but child knows about his parent). So you simply typecast it into your child cell.
Upvotes: 0
Reputation: 27345
[self.collectionView cellForItemAtIndexPath:indexPath]
returns UICollectionViewCell
. Not all UICollectionViewCell
objects are MNCalendarViewDayCell
, that's why you get the warning. By explicit cast (MNCalendarViewDayCell *)
you tell compiler that it is MNCalendarViewDayCell
.
Upvotes: 1
Reputation: 11764
So the first one grabs a pointer to a UICollectionViewCell
, which is what the base class of MNCalendarViewDayCell
is. However whilst it's a super class you can't just assign it to a subclass, so what the (MNCalendarViewDayCell *)
does is to say that you're going to cast the pointer from it's base class UICollectionViewCell
into the subclass instead. That's why the second one works, as you're converting it to the right type needed for assignment.
Upvotes: 0