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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.12 04:11:56