Segue Push跳转时UIImage返回nil,图片URL解析显示异常
解决Segue跳转时无法获取已显示图片的问题
这个问题我做iOS项目时也踩过一模一样的坑!核心原因是你用的downloadImage是异步网络请求——cell里的图片能显示是因为下载完成后回调更新了UI,但你在didSelectRowAt里跳转时,要么图片还没下载完成,要么因为cell复用机制,你拿到的不是当前选中cell的真实图片(可能是复用了其他未加载完成的cell)。
下面给你几个落地可行的解决方案:
方案1:把图片提前缓存到数据源模型里
最稳妥的思路是将下载好的图片存到你的数据源模型中,而不是只临时存在cell的UIImageView里。
步骤1:给Recipe模型添加缓存属性
假设你的Recipe模型结构如下,新增一个可修改的cachedImage属性:
struct Recipe { let image: String // 图片URL字符串 var cachedImage: UIImage? // 新增的本地缓存图片属性 // 其他业务属性... }
步骤2:修改downloadImage方法,添加完成回调
如果你的downloadImage是UIImageView的扩展,给它加个completion回调,方便拿到下载完成的图片:
extension UIImageView { func downloadImage(from urlString: String, completion: ((UIImage?) -> Void)? = nil) { guard let url = URL(string: urlString) else { completion?(nil) return } URLSession.shared.dataTask(with: url) { data, _, error in guard let data = data, let image = UIImage(data: data) else { completion?(nil) return } DispatchQueue.main.async { self.image = image completion?(image) // 把下载好的图片通过回调返回 } }.resume() } }
步骤3:在cellForRowAt中缓存图片到数据源
调用downloadImage时,把下载好的图片同步存到对应的Recipe模型里:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "RecipeCell", for: indexPath) as! RecipeCell let recipe = tableViewDataSource[indexPath.item] cell.recipeImage.downloadImage(from: recipe.image) { [weak self] downloadedImage in guard let self = self else { return } // 缓存到数据源模型 self.tableViewDataSource[indexPath.item].cachedImage = downloadedImage } // 其他cell内容配置... return cell }
方案2:跳转时直接使用缓存的图片
在didSelectRowAt方法里,直接从数据源模型取缓存的图片,而不是去cell的UIImageView中获取:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { let selectedRecipe = tableViewDataSource[indexPath.item] let storyboard = UIStoryboard(name: "Main", bundle: nil) // 假设你的详情页控制器是RecipeDetailViewController guard let detailVC = storyboard.instantiateViewController(withIdentifier: "RecipeDetailVC") as? RecipeDetailViewController else { return } // 同时传递缓存图片和原URL,做双重保障 detailVC.cachedRecipeImage = selectedRecipe.cachedImage detailVC.recipeImageURL = selectedRecipe.image navigationController?.pushViewController(detailVC, animated: true) }
方案3:详情页兼容缓存为空的情况
万一跳转时图片还没下载完成,在详情页里用URL再次触发下载:
class RecipeDetailViewController: UIViewController { var cachedRecipeImage: UIImage? var recipeImageURL: String? @IBOutlet weak var detailImageView: UIImageView! override func viewDidLoad() { super.viewDidLoad() // 优先使用缓存图片 if let cachedImage = cachedRecipeImage { detailImageView.image = cachedImage } else if let url = recipeImageURL { // 缓存为空时重新下载 detailImageView.downloadImage(from: url) } } }
这样处理后,不管跳转时图片有没有下载完成,详情页都能稳定显示目标图片啦~
内容的提问来源于stack exchange,提问作者miranda
相关产品推荐
相关产品推荐

