Delegate失效:点击Cell后数据无法传递至详情ViewController
问题分析与修复方案
核心问题
- Delegate赋值逻辑错误:你在
DetailsViewController的viewDidLoad里新建了一个LibraryVC实例并设置代理,但这个新实例和当前展示CollectionView的LibraryVC是完全独立的对象,导致原LibraryVC的movieDelegate始终为nil,调用代理方法时无响应。 - 图片加载方式错误:
UIImage(named:)仅用于加载本地资源图片,而你传入的是网络图片URL字符串,无法通过这种方式加载网络图片。
修复步骤
方案一:直接传值(推荐,逻辑更直观)
修改LibraryVC的didSelectItemAt方法
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let movieItem = dataSource.itemIdentifier(for: indexPath) else { return } print(movieItem.image.original) // 创建详情VC并直接传递图片URL let detailsVC = DetailsViewController() detailsVC.movieImageUrlString = movieItem.image.original let navController = UINavigationController(rootViewController: detailsVC) present(navController, animated: true) }
修改DetailsViewController代码
// 新增存储图片URL的属性 var movieImageUrlString: String? override func viewDidLoad() { super.viewDidLoad() // 删除原来新建LibraryVC的无效代码 // 加载网络图片 guard let urlString = movieImageUrlString, let url = URL(string: urlString) else { return } URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, error == nil else { return } // 回到主线程更新UI DispatchQueue.main.async { self?.movieImage.image = UIImage(data: data) } }.resume() } // 删除无用的Delegate扩展
方案二:修正Delegate使用方式(不推荐,没必要绕弯)
修改LibraryVC的didSelectItemAt方法
// 先把代理属性改成可选类型,避免强制解包崩溃 var movieDelegate: LibraryVCDelegate? func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { guard let movieItem = dataSource.itemIdentifier(for: indexPath) else { return } let detailsVC = DetailsViewController() // 将当前LibraryVC的代理设置为详情VC self.movieDelegate = detailsVC let navController = UINavigationController(rootViewController: detailsVC) present(navController, animated: true) // 调用代理方法 movieDelegate?.didGetMovie(moive: movieItem.image.original) }
修改DetailsViewController代码
override func viewDidLoad() { super.viewDidLoad() // 删除原来新建LibraryVC的无效代码 } extension DetailsViewController: LibraryVCDelegate { func didGetMovie(moive: String) { // 改用网络加载图片 guard let url = URL(string: moive) else { return } URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, error == nil else { return } DispatchQueue.main.async { self?.movieImage.image = UIImage(data: data) } }.resume() } }
额外提示
- 网络图片加载建议使用第三方库(如Kingfisher、SDWebImage),自带缓存、错误处理等功能,比手写
URLSession更稳定。 - 避免用
!强制解包可选类型,改用?可选链式调用,防止nil崩溃。
内容的提问来源于stack exchange,提问作者Ethan
相关产品推荐
相关产品推荐

