无法从 UITableViewCell 加载 UICollectionView

Posted

技术标签:

【中文标题】无法从 UITableViewCell 加载 UICollectionView【英文标题】:Can't load UICollectionView from UITableViewCell 【发布时间】:2019-02-27 13:21:37 【问题描述】:

我的UITableViewController 具有内置UICollectionView 的单元格。我想将UIViceController 逻辑移动到单元类-JournalSceneCell。为了在控制器中实现它,我为单元格的变量 imagesFilename 分配了一个新值

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    guard let cell = ... as? JournalSceneCell
    cell.imagesFilename = Array(journalRef!.entries[indexPath.row].imagesFilenames)
    return cell

图像可能很大,为了让 UITableViewController 尽可能快地加载,我尝试在 didSet 部分执行加载图像并使用后台线程:

class JournalSceneCell: UITableViewCell, UICollectionViewDataSource 

    @IBOutlet weak var entryTitle: UILabel!
    @IBOutlet weak var locationText: UILabel!
    @IBOutlet weak var desctiptionText: UILabel!
    @IBOutlet weak var editButton: UIButton!
    @IBOutlet weak var shareButton: UIButton!
    @IBOutlet var collectionViewRef: UICollectionView!

    convenience init() 
        self.init()
        self.collectionViewRef.dataSource = self
   

    struct ImageEntry 
        var image:UIImage
        var imageURL:URL
    

    let collectionCellID = "JournalCollectionCellID"

    var selectedImages = [ImageEntry]()

    var imagesFilename = [String]() 
        didSet 
            DispatchQueue.global(qos: .background).async 
                let documentURL = try! FileManager.default.url(for: .documentDirectory,
                                                               in: .userDomainMask,
                                                               appropriateFor: nil,
                                                               create: true)
                self.selectedImages.removeAll()
                for imageName in self.imagesFilename 
                    let imageURL = documentURL.appendingPathComponent(imageName)
                    let imageData = try! Data(contentsOf: imageURL)
                    let img = UIImage(data: imageData)!
                    self.selectedImages.append(ImageEntry(image: img, imageURL: imageURL))
                
                DispatchQueue.main.async 
                    self.collectionViewRef.reloadData()
                
            
        
    

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
        return selectedImages.count
    


    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 
        guard let cell = collectionViewRef.dequeueReusableCell(withReuseIdentifier: collectionCellID,
                                                        for: indexPath) as? JournalCollectionCell else 
            fatalError("Cannot connect a collection cell")
        

        cell.imageView.image = selectedImages[indexPath.row].image
        return cell

    


问题:JournalSceneCell 根本没有从 UICollectionViewDataSource 调用 collectionView func。一切都通过 IB 连接,添加了重用标识,但什么也没发生

【问题讨论】:

【参考方案1】:

在tableView Cell中重新加载集合视图,它会工作

cell.collectionViewRef.reloadData()

【讨论】:

我去试试【参考方案2】:

你需要设置

override func awakeFromNib() 
   super.awakeFromNib()
   self.collectionViewRef.dataSource = self
   self.collectionViewRef.delegate = self


class JournalSceneCell: UITableViewCell, UICollectionViewDataSource,UICollectionViewDelegate 

【讨论】:

其实我试过了。它没有帮助。我也不需要委托 为什么?这是来自本地图库的图片 确保您的文档文件有图像,或者您需要像let img = UIImage(named: "name.png")!这样的主包 我又检查了一遍 - 它有图片【参考方案3】:

convenience init() 没有被调用。 最后我通过将函数loadImages(fileNameArray:[String]) 添加到JournalSceneCell 来解决问题:

func loadImages(fileNameArray:[String]) 
    self.imageSetView.dataSource = self
    DispatchQueue.global(qos: .background).async 
        let documentURL = try! FileManager.default.url(for: .documentDirectory,
                                                       in: .userDomainMask,
                                                       appropriateFor: nil,
                                                       create: true)
        self.selectedImages.removeAll()
        for imageName in fileNameArray 
            let imageURL = documentURL.appendingPathComponent(imageName)
            let imageData = try! Data(contentsOf: imageURL)
            let img = UIImage(data: imageData)!
            self.selectedImages.append(ImageEntry(image: img, imageURL: imageURL))
        

        DispatchQueue.main.async 
            self.imageSetView.reloadData()
        

    

后来我只是从tableView(_:cellForRowAt:)调用它

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    guard let cell = .. as? JournalSceneCell,
    cell.loadImages(fileNameArray:Array(...))
    return cell

【讨论】:

【参考方案4】:

我遇到了类似的问题,因为 UICollectionView 甚至没有在 UITableViewCell 中绘制,所以我必须在集合视图上设置最小高度 NSLayoutConstraint

在这种情况下,您可能需要 UICollectionView 的高度是动态的,但我不完全确定您的最佳路线。

【讨论】:

我要试试。它是通过 InterfaceBuilder 连接和构建的,但可能出了点问题。

以上是关于无法从 UITableViewCell 加载 UICollectionView的主要内容,如果未能解决你的问题,请参考以下文章

将自定义 UITableViewCell 从 nib 加载到 Swift 中的 UIViewController

如何从自定义 UITableViewCell 调用操作以重新加载 tableView

从 NIB 加载自定义 UITableViewCell 问题

UITableViewCell 背景隐藏 UI 元素

加载 tableView 后如何更新 UITableViewCell 高度

UITableViewCell 异步图片加载布局