UITableViewCell内置UICollectionView数据源方法未调用问题求助
解决JournalSceneCell中UICollectionView数据源方法未调用的问题
首先,最核心的问题出在你的convenience init()上——这个初始化方法根本不会被执行!因为从Storyboard/XIB加载的UITableViewCell,系统会调用init?(coder:)方法来初始化,而不是你自定义的便利构造器。这就导致collectionViewRef.dataSource = self这句代码从来没被执行,UICollectionView自然不知道要找哪个对象要数据,数据源方法也就不会被调用了。
接下来给你一步步的解决方案:
1. 修复初始化方法,正确设置CollectionView的DataSource
把原来的便利构造器删掉,换成重写系统的初始化方法,并抽取出一个设置CollectionView的私有方法:
class JournalSceneCell: UITableViewCell, UICollectionViewDataSource { // ... 你的IBOutlet和属性定义 // 重写代码初始化的方法 override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setupCollectionView() } // 重写从XIB/Storyboard加载的初始化方法 required init?(coder: NSCoder) { super.init(coder: coder) setupCollectionView() } // 专门负责CollectionView的基础设置 private func setupCollectionView() { self.collectionViewRef.dataSource = self // 如果没有在IB里注册JournalCollectionCell,取消下面注释(二选一即可) // collectionViewRef.register(JournalCollectionCell.self, forCellWithReuseIdentifier: collectionCellID) } // ... 你的其他方法 }
2. 检查IB中的关键设置
- 确保
collectionViewRef这个IBOutlet已经正确连接到Storyboard/XIB里的UICollectionView,没有出现感叹号或者断开的情况。 - 检查UICollectionView的复用标识符:IB里设置的标识符要和代码里的
collectionCellID完全一致(包括大小写)。 - 确认UICollectionView的
dataSource和delegate在IB里没有被错误连接到其他对象(比如你的UITableViewController),如果有连接,直接删掉——我们已经通过代码设置了数据源。
3. 优化异步加载代码(避免崩溃+线程安全)
你当前的didSet里用了大量try!和强制解包,一旦图片加载失败或者文件路径错误,会直接导致崩溃。另外,在后台线程直接修改selectedImages也存在线程安全隐患,建议改成下面的写法:
var imagesFilename = [String]() { didSet { DispatchQueue.global(qos: .background).async { // 用临时数组存储加载的图片,避免后台线程修改实例变量 var tempImageEntries = [ImageEntry]() guard let documentURL = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else { print("无法获取文档目录") return } for imageName in self.imagesFilename { let imageURL = documentURL.appendingPathComponent(imageName) // 用可选绑定替代强制解包,容错性更强 if let imageData = try? Data(contentsOf: imageURL), let image = UIImage(data: imageData) { tempImageEntries.append(ImageEntry(image: image, imageURL: imageURL)) } else { print("加载图片失败:\(imageURL)") // 这里可以添加占位图逻辑,比如: // tempImageEntries.append(ImageEntry(image: UIImage(named: "placeholder")!, imageURL: imageURL)) } } // 回到主线程更新UI和数据 DispatchQueue.main.async { self.selectedImages = tempImageEntries // 用可选调用避免collectionViewRef为nil的情况 self.collectionViewRef?.reloadData() } } } }
最后验证
做完上面的修改后,重新运行项目,应该就能看到UICollectionView正常加载图片了。如果还是不行,可以检查一下imagesFilename是否确实被赋值了有效内容,确保数组里的文件名都是文档目录下存在的图片文件名。
内容的提问来源于stack exchange,提问作者Alex
相关产品推荐
相关产品推荐

