UICollectionView неправильно прокручивается - PullRequest
0 голосов
/ 04 февраля 2020

Я заполняю UICollectionView, где ячейки полноэкранные, и они прокручиваются по горизонтали. На экране отображаются правильные данные, но когда я нажимаю кнопку, чтобы распечатать текущую цену, она продолжает печатать цену для следующего indexPath. Я считаю, что я делаю что-то неправильно, когда дело доходит до прокрутки. Если pagingEnabled включен или выключен, это также не имеет значения.

   class PostCell: UICollectionViewCell {
let containerView:UIView = {
       let view = UIView()
       view.translatesAutoresizingMaskIntoConstraints = false
       view.clipsToBounds = true
       return view
   }()

let priceLabel:UILabel = {
         let label = UILabel()
         label.font = UIFont.boldSystemFont(ofSize: 20)
         label.text = "price"
         label.textColor = .black
         label.translatesAutoresizingMaskIntoConstraints = false
         return label
     }()
let myButton: UIButton = {
    let button = UIButton(type: .system)
    button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
    button.backgroundColor =  .red 
    return button

}()
func set(name: String, brand: String, price: String){
       priceLabel.text = price

   }
  override init(frame: CGRect) {
     super.init(frame: frame)
    self.contentView.addSubview(containerView)
    containerView.addSubview(priceLabel)
    containerView.addSubview(myButton)
    setupCellConstraints()
    }
     private func setupCellConstraints(){

       containerView.anchor(top: contentView.topAnchor, left: contentView.leftAnchor, bottom: contentView.bottomAnchor, right: contentView.rightAnchor, paddingTop: 0, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)

       nameLabel.anchor(top: containerView.topAnchor, left: nil, bottom: nil, right: nil, paddingTop: 50, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    brandLabel.anchor(top: nameLabel.bottomAnchor, left: nil, bottom: nil, right: nil, paddingTop: 50, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    priceLabel.anchor(top: brandLabel.bottomAnchor, left: nil, bottom: nil, right: nil, paddingTop: 50, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 0, height: 0)
    myButton.anchor(top: priceLabel.bottomAnchor, left: nil, bottom: nil, right: nil, paddingTop: 60, paddingLeft: 0, paddingBottom: 0, paddingRight: 0, width: 70, height: 70)

   }
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}



   class CollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {

 let cellId = "cellId"
 var itemsArr = [Item]()
     init() {
       super.init(collectionViewLayout: UICollectionViewFlowLayout())
   }
   required init?(coder: NSCoder) {
       fatalError("init(coder:) has not been implemented")
   }

  private var collectionViewFlowLayout: UICollectionViewFlowLayout {
    return collectionViewLayout as! UICollectionViewFlowLayout
}
override func viewDidLoad() {
    parseData()
    collectionView.showsHorizontalScrollIndicator = false
    collectionView.showsVerticalScrollIndicator = false
    collectionViewFlowLayout.minimumLineSpacing = 0
    self.collectionView.isPagingEnabled = true
    if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
        layout.scrollDirection = .horizontal
    }

    collectionView?.register(PostCell.self, forCellWithReuseIdentifier: cellId)

} 

 func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    return CGSize(width: view.frame.width, height: view.frame.height)
   }

override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return itemsArr.count
}

@objc func buttonPressed(){
    print(price)
}

var price: String = ""
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

      let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! PostCell
    let item = itemsArr[indexPath.row]]
    price = item.price
    cell.set(name: item.name, brand: item.brand, price: item.price)
    cell.myButton.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside)
      print(item)
      return cell
  }

Ответы [ 2 ]

0 голосов
/ 04 февраля 2020

У вас есть только одна переменная «цена», и она хранит данные последней видимой ячейки. Ваш лог c неверен. Вы должны иметь значение «цена» для каждой ячейки.

Вот еще одно предложение для вас;

// we capture the tag of the button and tag points the index of the array.
@objc func buttonPressed(_ sender : UIButton){
    let item = itemArr[sender.tag]
    print(item)
}

// var price: String = "" // that variable is meaningless.
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! PostCell
    let item = itemsArr[indexPath.row]]
    // price = item.price // that line is meaningless. 
    cell.set(name: item.name, brand: item.brand, price: item.price)
    cell.myButton.tag = indexPath.row // added that line.
    cell.myButton.addTarget(self, action: #selector(buttonPressed(:)), for: .touchUpInside) // changed that line little bit.
    print(item)
    return cell
}
0 голосов
/ 04 февраля 2020

Причина:

Это связано с тем, что cellForItemAt вызывается несколько раз при создании или повторном использовании нового cell. Таким образом, сохраненный price в значении CollectionViewController будет для cell, для которого cellForItemAt был вызван недавно.

Решение:

Вместо сохранения значения price в CollectionViewController и последующей его печати используйте closure для получения точного значение price для определенного cell.

В PostCell создайте handler и вызовите его в buttonPressed() методе, установленном как target из myButton, т.е.

class PostCell: UICollectionViewCell {
    //rest of the code...

    var handler: ((String?)->())? //here....

    let myButton: UIButton = {
        let button = UIButton(type: .system)
        button.titleLabel?.font = UIFont.systemFont(ofSize: 18)
        button.backgroundColor =  .red
        button.addTarget(self, action: #selector(buttonPressed), for: .touchUpInside) //here....
        return button
    }()

    @objc func buttonPressed(){
        handler?(priceLabel.text) //here....
    }
}

Теперь в collectionView(_:cellForItemAt:) установите handler для cell, т.е.

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! PostCell
    let item = itemsArr[indexPath.row]
    cell.set(name: item.name, brand: item.brand, price: item.price)
    cell.handler = {(price) in //here....
        print(price)
    }
    return cell
}
...