难以处理集合视图单元的可重用性。

时间:2018-05-06 19:31:17

标签: ios uicollectionview swift4

我正在尝试使用集合视图创建座位计划。因为每个座位都有一个特定的数字,这意味着每个单元格都有一个显示座位号的标签。我使用自定义集合视图布局来创建座位图,座位图是2向滚动的。一切顺利,直到座位图滚动。一旦滚动座位图,就会改变座位号的值。我知道这是因为集合视图单元的可重用性,但我无法找到出路。我试图在堆栈中搜索答案,但没有什么对我有用。请帮忙..

这是我的视图控制器:

class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var collectionView: UICollectionView!
    var seatNo = 0
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.dataSource = self
        collectionView.delegate = self
    }

    // func for number of section in collection view
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 10
    }

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

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell
        if indexPath.row == 0 {
            seatNo = 1
        }
        cell.assignSeat(seat: seatNo)
        seatNo += 1
        cell.seatNumber.text = "\(cell.seat ?? 0)"
        return cell
    }

}

这是我的集合视图单元格:

class CollectionViewCell:UICollectionViewCell {

  @IBOutlet weak var seatNumber: UILabel!
    var seat: Int?
    override func prepareForReuse() {
        seatNumber.text = ""
        seat = 0
    }
    func assignSeat(seat: Int) {
        self.seat = seat
    }
}

如果需要,这里是自定义集合视图布局的代码:

class CustomCollectionLayout: UICollectionViewLayout {

        // var for cell height
        var CELL_HEIGHT: Double!

        //Variable for cell width
        var CELL_WIDTH: Double!

        // Variable for the status bar height
        let STATUS_BAR = UIApplication.shared.statusBarFrame.height

        // Array to store the cell attributes
        var cache = [UICollectionViewLayoutAttributes]()

        //variable to define the content size
        var contentSize = CGSize.zero

        // another variable to store the cell atributes
        var cellAttrsDictionary = [UICollectionViewLayoutAttributes]()

        // variable to store the cell padding
        var cellPadding: Double!

        // func that defines the collection view content size
        override var collectionViewContentSize: CGSize{
            return self.contentSize
        }

        // func to prepare the collection view
        // how the cells are to be mapped is defined in this function
        override func prepare() {

            // assigning the values to the variables
            CELL_HEIGHT = 44
            CELL_WIDTH = 44
            cellPadding = 2

            // Cycle through each section of the data source.
            if collectionView?.isDragging == false{
                if collectionView!.numberOfSections > 0 {
                    for section in 0...collectionView!.numberOfSections-1 {

                        // Cycle through each item in the section.
                        if collectionView!.numberOfItems(inSection: section) > 0 {
                            for item in 0...collectionView!.numberOfItems(inSection: section)-1 {

                                // storing the index of the current cell
                                let cellIndex = NSIndexPath(item: item, section: section)

                                // defining the x and y coordinates for the other cells
                                let xPos = Double(item) * CELL_WIDTH
                                let yPos = Double(section) * CELL_HEIGHT

                                //creating the frame for the cell
                                let frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT)

                                //providing the padding
                                let cellFinalAttribute = frame.insetBy(dx:CGFloat(cellPadding) ,dy:CGFloat(cellPadding))

                                //storing the cellattributes in the array
                                let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
                                cellAttributes.frame = cellFinalAttribute
                                cellAttrsDictionary.append(cellAttributes)
                            }

                        }

                    }
                }

                // Update content size.
                let contentWidth = Double(collectionView!.numberOfItems(inSection: 0)) * CELL_WIDTH
                let contentHeight = Double(collectionView!.numberOfSections) * CELL_HEIGHT
                self.contentSize = CGSize(width: contentWidth, height: contentHeight)
            }
        }

        // func that returns the cell attributes for the elements that are visible in the screen
        override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {

            // Create an array to hold all elements found in our current view.
            var attributesInRect = [UICollectionViewLayoutAttributes]()

            // Check each element to see if it should be returned.
            for cellAttributes in cellAttrsDictionary {
                if rect.intersects(cellAttributes.frame) {
                    attributesInRect.append(cellAttributes)
                }
            }

            // Return list of elements.
            return attributesInRect
        }

        //func that returns the cell attributes for the indexpath
        override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
            return cellAttrsDictionary[indexPath.row]
        }

        //this func call the prepare func if the user scrolls if returned true
        override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
            return false
        }
    }

1 个答案:

答案 0 :(得分:0)

不是使用数组,为什么不说

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell


    let seatNo = (indexPath.row + 1) + (indexPath.section * 15) 
    cell.assignSeat(seat: seatNo)
    cell.seatNumber.text = "\(cell.seat ?? 0)"
    return cell
}

我还没有运行此代码,但想法是使用

indexPath.row + 1

让座位位于其中。

然后我们可以使用

indexPath.section * 15 // (number of seats per row should be declared static)

获取前一行中的座位数。在第一行中,该部分将为0,因此不会添加任何内容,但后续行将正确添加

我强烈建议在文件顶部声明15和10以避免幻数