Reputation: 267
I have a fairly vanilla UITableView in my app used to display an image and text in the default/standard way. The first time a UITableViewCell is requested I return it with a placeholder image and start an asynchronous download of the real image. When the download is complete I replace the placeholder image.
If a download fails, the placeholder image remains. Clicking on such a row acts normally. If the download is successful, clicking on a row with the intended image leads to the UIImageView expanding to the height of the row (and the width increases at scale). The UIImageView never returns to normal size. Crude attempts to set the frame of the UIImageView do not alleviate the issue of mysterious resizing.
// from my - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath; method
// after boilerplate cell dequeuing code
cell.textLabel.text = [selectedNoun title];
// add placeholder image
UIImage *placeholderImage = [UIImage imageNamed:@"placeholder.png"];
cell.imageView.image = placeholderImage;
[cell.imageView setContentMode:UIViewContentModeScaleAspectFit];
//...
// If the image has been downloaded I set it
cell.imageView.image = iconDownloader.image;
This is driving me nuts. It actually only happens in one of two tables in my app, but after comparing them line or line I can't see any difference. Hoping that someone has come across this before.
Thanks!
EDIT: I don't have a good explanation for my solution other than to say that images over a certain size appear to lead to this behavior and the use of actual thumbnails (even images somewhat bigger than the UIImageView's frame) do not exhibit this behavior.
Upvotes: 23
Views: 11259
Reputation: 826
In my case, I faced this issue in iOS 12 however iOS 13 works fine.
I changed UIImageView
to UIButton
and set background image as like below which fixes my issue.
cell.imageButton.setBackgroundImage(UIImage(named: "name_of_the_image", for: UIControl.State.normal)
I know this is way too late to post but someone might find it helpful.
Upvotes: 0
Reputation: 4536
My issue was slightly different, I had a custom UITableViewCell
with own UIImageView and when cell disappeared and reappeared, the image would be incorrect size. My problem was that I was setting cell.imageView
in one place and cell.thumbnail
(custom image) in another, so I changed all references to cell.thumbnail.
Hopefully it helps someone in the future with similar issue.
Upvotes: 3
Reputation: 31
This answer helped me. But I had to make sure to call [cell layoutSubviews]
in the method that actually does the setting, like this:
cell.imageView.image = image;
[cell layoutSubviews];
Hope this can be of use to you!
Upvotes: 3
Reputation: 1274
If you have custom UITableViewCell then make sure that your UIImageView is not named with "imageView"
Upvotes: 25
Reputation: 2992
If you reload the tableview when it finish loading, the image get the size that it was suppose to have
[self.tableview reloadData];
Upvotes: 0
Reputation: 131
follow these steps:
Upvotes: 1
Reputation: 9
doing something like
CGRect bounds = [self bounds];
[self setImage:image];
[self setBounds:bounds];
when setting image fixes the problem for me
Upvotes: 0
Reputation: 2992
I had the same problem, and I didn't figure out the reason for that. Anyway, it's something related to the placeholder image: if you load an image of the same size that the placeholder, no resize will be performed, but if the sizes don't match, the loaded image will be resized to the placeholder dimensions, and resized again when clicked.
So, if you want to avoid the problem, use a placeholder that matches the row height.
Upvotes: 1
Reputation: 21967
The only things that come to mind that effect the size & appearance of a view within its superview are:
Are you changing the frame/bounds/center properties anywhere? Where/how is the frame set initially?
imageView.autoResizingMask
should be set to UIViewAutoResizingNone
imageView.clipsToBounds
should be set to YES
EDIT: more suggestions
I'm shooting in the dark b/c your posted code looks fine and if you've set imageView.clipsToBounds
that should constrain the drawn image to the imageView
frame. Here are a couple more things to try:
Implement tableView:willDisplayCell:forRowAtIndexPath:
and set the imageView
properties there. If imageView.frame
is the problem, this likely won't fix it.
Add your own UIImageView
to the cell configured how you want it and don't use the built in imageView
property. If the behavior of the default cell is causing the problem this should work.
EDIT: large image problems
I don't know exactly how big the "really big images" are that you are currently using but they are likely the issue. From the UIImage
docs (emphasis is mine):
You should avoid creating UIImage objects that are greater than 1024 x 1024 in size. Besides the large amount of memory such an image would consume, you may run into problems when using the image as a texture in OpenGL ES or when drawing the image to a view or layer. This size restriction does not apply if you are performing code-based manipulations, such as resizing an image larger than 1024 x 1024 pixels by drawing it to a bitmap-backed graphics context. In fact, you may need to resize an image in this manner (or break it into several smaller images) in order to draw it to one of your views.
Upvotes: 11
Reputation: 2261
In these situations I use this Image loader framework. It includes a method to set a placeholder image of your choosing, while downloading images in the background, and as an added benefit it caches images guaranteeing the same image won't ever have to be downloaded twice. Its a great piece of work that I've found very useful for tableview image loading.
SDWebImage: https://github.com/rs/SDWebImage
Upvotes: 1
Reputation: 7103
This is pretty unlikely, but you should try to look into what happens to the frames of the UITableViewCell's subviews when its isSelected
property switches from NO
to YES
(I.e. what happens when you tap a cell). I doubt that will help much, but it's worth looking into (if you can find anything...that's all under the hood of UITableViewCell I would imagine).
You should also look into the imageview's clipsToBounds
property. Maybe that has something to do with it?
Upvotes: 0