You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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 ImageScrollView state on reuse ensures old zoom levels/content offsets don't interfere with new images.
  • Setting imageContentMode before 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 layoutSubviews ensures 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:11:02