简体   繁体   English

未显示集合视图,从不调用cellForItemAtIndexPath

[英]Collection View isn't being displayed, cellForItemAtIndexPath is never called

I have a UITableView with custom cells containing UIStackView . 我有一个UITableView与自定义单元格包含UIStackView As part of preparing a new cell, when the Table View adds new cells via its cellForRowAtIndexPath method, it instantiates and adds any collection views (of type MultaCollectionView ) and any UILabel which need to be added to the cell's Stack View (a cell may include various collection views). 作为准备新单元格的一部分,当表视图通过其cellForRowAtIndexPath方法添加新单元格时,它会实例化并添加任何集合视图(类型为MultaCollectionView )和任何需要添加到单元格的堆栈视图中的UILabel (单元格可能包含各种收藏意见)。 In theory, a stack view contains a sequence of Labels and Collection Views. 理论上,堆栈视图包含一系列标签和集合视图。

Although labels are displaying correctly, the Collection View is not being displayed at runtime. 虽然标签显示正确,但是在运行时不显示集合视图。 The Collection View I'm attempting to display is defined in a .xib Interface Builder document. 我试图显示的集合视图是在.xib Interface Builder文档中定义的。

The Collection View's numberOfSectionsInCollectionView method is getting called, however the collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) method is never called. 调用Collection View的numberOfSectionsInCollectionView方法,但是从不调用collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)方法。

Why is the collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) method never called? 为什么从不调用collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)方法? Why aren't Collection Views being rendered in the Stack View? 为什么不在堆栈视图中呈现集合视图?

import UIKit
private let reuseIdentifier = "Cell"

class MultaCollectionView: UICollectionView, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
        self.dataSource = self
    }
    class func instanceFromNib() -> UICollectionView {
        return UINib(nibName: "multas", bundle: nil).instantiateWithOwner(nil, options: nil)[0] as! UICollectionView
    }

    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
        return 1
    }


    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 2
    }

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath)
        return cell
    }

}

The parent TableView adds Cells via the following method: TableView通过以下方法添加Cells:

func addSubviewsToCellStack(cell: ArticuloTableViewCell, texto: [[String: String]]) {\            
    if isLabel == true {
            let label = UILabel()
            label.text = "blah"
            subview = label
            cell.textoStack.addArrangedSubview(subview)
        } else {
            let colview = MultaCollectionView.instanceFromNib() 
            cell.textoStack.addArrangedSubview(colview)
        }                        
    }

}

Since you are getting the call back for the numberOfSectionsInCollectionView this would suggest the datasource is connected up correctly but if a cell is not going to be visible based on the current layout then the collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) will not get called until it is needed. 由于您正在获取numberOfSectionsInCollectionView回调,这将表明数据源已正确连接,但如果基于当前布局不会显示单元格,则collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath)将无法获取在需要之前调用。 The reason a cell might not be visible could be because your sectionInsets for the collectionView are set large enough that the first cell would be positioned outside the visible area of the collectionView. 单元格可能不可见的原因可能是因为collectionView的sectionInsets设置得足够大,以至于第一个单元格将位于collectionView的可见区域之外。

Another reason could be that the collectionView's frame is too small to display any cells. 另一个原因可能是collectionView的框架太小而无法显示任何单元格。 If your collectionview as a size of {0,0} you should get the calls as you are seeing to the numberOfSectionsInCollectionView but will not get the calls to cellForItemAtIndexPath since the cells will not be visible. 如果您的集合cellForItemAtIndexPath大小为{0,0},您应该看到numberOfSectionsInCollectionView但不会调用cellForItemAtIndexPath因为单元格将不可见。

Perhaps try ensuring that your collectionView has a frame size that is large enough to display the cells you expect to see. 也许尝试确保您的collectionView的框架大小足以显示您希望看到的单元格。 You may be seeing the UILabels correctly because they have an implicit intrinsicContentSize which ensures they display well in a stackView whereas the CollectionView is just as happy to have a size of 0,0 as it would be with any other size. 你可能正确地看到了UILabel,因为它们有一个隐含的intrinsicContentSize ,可以确保它们在stackView中很好地显示,而CollectionView与任何其他大小的大小一样高兴。 Try giving the collectionView explicit width and height constraints to see if that helps. 尝试给出collectionView显式的宽度和高度约束,看看是否有帮助。

My hypothesis would be that since this is happening inside cells of a UITableView, whenever a table view cell gets put back in the "reuse pool", the delegates of the collection view get disconnected or disabled. 我的假设是,由于这发生在UITableView的单元格内部,每当表格视图单元格被放回“重用池”时,集合视图的委托就会断开连接或禁用。 This would depends on the code that provide cells to the table view (which we're not seeing in the code sample). 这将取决于为表视图提供单元格的代码(我们在代码示例中没有看到)。

There could also be some code elsewhere that clears the datasource from the collection view. 其他地方也可能有一些代码从集合视图中清除数据源。 (unlikely but worth checking) (不太可能,但值得检查)

I FINALLY got it to work. 我终于开始工作了。 When transitioning from a storyboard view controller to a non storyboard collection view controller you must do this while pushing to the controller : 从故事板视图控制器转换到非故事板集合视图控制器时,必须在推送到控制器时执行此操作:

func showChatLogController(user: User) {
    let chatLogController = ChatLogController(collectionViewLayout: UICollectionViewFlowLayout())
    chatLogController.user = user
    chatLogController.hidesBottomBarWhenPushed = true
    navigationController?.pushViewController(chatLogController, animated: true)

}

To be more specific you must use collectionViewLayout: UICollectionViewFlowLayout 更具体地说,您必须使用collectionViewLayout:UICollectionViewFlowLayout

The issue was resolved by overriding UIView 's intrinsicContentSize() method in my UICollectionView subclass as follows (check out this question ): 通过在我的UICollectionView子类中重写UIViewintrinsicContentSize()方法解决了这个问题 ,如下所示(查看这个问题 ):

override func intrinsicContentSize() -> CGSize {
    return self.collectionViewLayout.collectionViewContentSize()
}

As an aside, I had also forgotten to register a class for the Cell reuse identifier. 另外,我还忘记为Cell重用标识符注册一个类。 So I modified the initializer: 所以我修改了初始化程序:

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.delegate = self
    self.dataSource = self
    self.registerClass(UICollectionViewCell.self, forCellWithReuseIdentifier: reuseIdentifier)
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM