трудности, связанные с возможностью повторного использования ячейки представления коллекции. - PullRequest
0 голосов
/ 06 мая 2018

Я пытаюсь создать план рассадки, используя вид коллекции. При этом каждое место будет иметь определенный номер, что означает, что каждая ячейка будет иметь метку, которая отображает номер места. Я использую пользовательский макет представления коллекции, чтобы создать карту мест, и карта мест прокручивается в двух направлениях. Все идет хорошо, пока карта мест не будет прокручена. после прокрутки карты мест значения номеров мест меняются. Я знаю, что это из-за возможности повторного использования ячеек представления коллекции, но я не могу найти выход. Я пытался найти ответ в стеке, но у меня ничего не работает. пожалуйста, помогите ..

вот мой контроллер вида:

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
    }

}

и вот моя ячейка просмотра коллекции:

класс 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 голосов
/ 07 мая 2018

Вместо того, чтобы использовать массив, почему бы не сказать

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 в верхней части вашего файла, чтобы избежать магических чисел

...