Swift4中UITableView内ImageScrollView可见单元格图片尺寸异常问题
Hey there, let's break down the issues you're facing and fix them step by step!
First, the main problem where images get too wide when navigating back to the table view is almost certainly due to UITableViewCell reuse—the ImageScrollView is retaining old state from previous cells, which messes up the new image layout. Here's how to fix that:
1. Reset ImageScrollView State on Cell Reuse
Add prepareForReuse() to your cell class to clear out any leftover state before the cell gets reused:
override func prepareForReuse() { super.prepareForReuse() // Clear the image and reset scroll/zoom state skiImageScrollView.display(image: nil) skiImageScrollView.zoomScale = 1.0 skiImageScrollView.contentOffset = .zero skiImageView.image = nil // Clear the placeholder/old image }
2. Fix the ConfigureCell Flow
Your current code sets imageContentMode after displaying the image, which can cause layout inconsistencies. Also, start with a clean state at the top of configureCell:
func configureCell(ski: Ski) { self.ski = ski // Reset state first to avoid reuse issues skiImageScrollView.display(image: nil) skiImageScrollView.zoomScale = 1.0 skiImageScrollView.contentOffset = .zero let imageUrl = ski.imageUrl! guard let url = URL(string: imageUrl) else { return } skiImageView.sd_setImage(with: url, placeholderImage: placeholderImage, options: [.retryFailed, .continueInBackground]) { [weak self] image, error, cacheType, url in guard let self = self, let loadedImage = image else { if let error = error { print("ConfigureCell Error : \(error)") } return } // Rotate the image (we'll optimize this next) let rotatedImage = self.imageRotatedByDegrees(oldImage: loadedImage, deg: 90.0) // Set content mode BEFORE displaying the image self.skiImageScrollView.imageContentMode = .widthFill // Display the image and force layout update self.skiImageScrollView.display(image: rotatedImage) self.skiImageScrollView.setNeedsLayout() self.skiImageScrollView.layoutIfNeeded() } }
3. Optimize Image Rotation
Your manual rotation code works, but using UIImage.Orientation is more efficient and avoids potential bitmap context issues:
func imageRotatedByDegrees(oldImage: UIImage, deg degrees: CGFloat) -> UIImage { let targetOrientation: UIImage.Orientation switch degrees { case 90: targetOrientation = .right case 180: targetOrientation = .down case 270: targetOrientation = .left default: targetOrientation = .up } // Use the original image's CGImage and scale for better quality guard let cgImage = oldImage.cgImage else { return oldImage } return UIImage(cgImage: cgImage, scale: oldImage.scale, orientation: targetOrientation) }
Fixing the "Tap/Set Down Image Shift" Issue
That weird offset when moving the phone is likely related to layout not updating properly. Add this to your cell class to ensure ImageScrollView re-lays out correctly when the cell's bounds change:
override func layoutSubviews() { super.layoutSubviews() // Re-apply the image and content mode if we have one loaded if let currentImage = skiImageScrollView.image { skiImageScrollView.imageContentMode = .widthFill skiImageScrollView.display(image: currentImage) skiImageScrollView.setNeedsLayout() } }
Bonus: Remove Unnecessary UIImageView
You don't actually need skiImageView—you can use SDWebImageManager to load the image directly without an extra UIImageView, which cleans up your code:
// Replace the skiImageView.sd_setImage block with this: SDWebImageManager.shared.loadImage(with: url, options: [.retryFailed, .continueInBackground], progress: nil) { [weak self] image, _, error, _, _, _ in guard let self = self, let loadedImage = image else { if let error = error { print("ConfigureCell Error : \(error)") } return } let rotatedImage = self.imageRotatedByDegrees(oldImage: loadedImage, deg: 90.0) self.skiImageScrollView.imageContentMode = .widthFill self.skiImageScrollView.display(image: rotatedImage) self.skiImageScrollView.setNeedsLayout() }
Let me explain why these fixes work:
- Resetting the
ImageScrollViewstate on reuse ensures old zoom levels/content offsets don't interfere with new images. - Setting
imageContentModebefore displaying the image tells the scroll view how to layout the image from the start. - The optimized rotation method uses system-level image handling, which is more reliable than manual bitmap drawing.
- Overriding
layoutSubviewsensures the scroll view adjusts correctly if the cell's size changes (like when the phone is moved, which might trigger layout updates).
内容的提问来源于stack exchange,提问作者andysanc

