ios - collectionView didSelectItemAt superview 没有选择正确的对象

标签 ios swift uicollectionview

我在名为 MyCropView 的 UIView 类中的 collectionView 中有一个传感器列表,我在其中显示了有关该裁剪的一些数据。 我试图更改某些传感器的值,例如每次单击时的图标和背景颜色。

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let myCropCard = collectionView.superview as! MyCropCard

    let sensor = myCropCard.sensors[indexPath.row]
    let cell = myCropCard.superview

    //Change the color and icon of the sensors 
    if let cell = collectionView.cellForItem(at: indexPath) as? MyCollectionViewCell {
        //Previous cell in grey
        if !self.lastSelectedIndexPath.isEmpty {
            let lastCell = collectionView.cellForItem(at: self.lastSelectedIndexPath) as? MyCollectionViewCell
            lastCell?.imageView.backgroundColor = UIColor(red: 0.95, green: 0.95, blue: 0.95, alpha: 1.0)
            lastCell?.imageView.image = UIImage(named: self.lastSelectedImageName )
        }

        //Makes sensor green onSelect
        cell.imageView.backgroundColor = UIColor(red: 0.882, green: 0.95, blue: 0.882, alpha: 1.0)
        cell.imageView.image = UIImage(named: sensor.getType() )
        self.lastSelectedIndexPath = indexPath
        self.lastSelectedImageName = String(format: "%@_deactivated", sensor.getType())
    }

    //Show all the alerts of each sensor
    for alert:Alert in sensor.getAlerts() {
        let viewSensor = cell?.viewWithTag(300) as! SensorView
        viewSensor.lblSensor.text = sensor.getTipo()
        viewSensor.lblBotLog.text = alerta.getNombreDispositivo()
        viewSensor.lblMin.text = String(format: "MIN %.0f", alert.getMin())
        viewSensor.lblMax.text = String(format: "MAX %.0f", alert.getMax())
        viewSensor.btnDel.tag = Int(alert.getId() + 1000) 
        viewSensor.btnDel.addTarget(
            self,
            action: #selector( viewSensor.deleteAlert(_:) ),
            for: .touchUpInside
        )
        viewSensor.isHidden = false
    }

}

collectionView 是我们拥有的传感器列表。它适用于第一个 MyCropCard,但不适用于多个 MyCropCard。 Superview 使用它们中的第一个 cropCard,而不是 collectionView 的父级。

我想知道如何才能正确拥有所选 collectionView 的父级?

最佳答案

您的代码中充斥着不必要的逻辑相关代码,这些代码可能与问题无关。 此外,广泛使用 tag这使得代码不可扩展且难以维护,因此它可能需要大量重构。

以下代码基本上是您想要实现的目标的 MWE(如果我误解了您的问题,请告诉我)。

解释一下代码,这是一个自定义的tableViewCell:

class TableViewCell: UITableViewCell {
  var collectionView: UICollectionView? {
    didSet {
      guard let collectionView = collectionView else { return }
      contentView.addSubview(collectionView)
      collectionView.translatesAutoresizingMaskIntoConstraints = false
      collectionView.backgroundColor = .white
      setupCollectionViewLayout(collectionView)
    }
  }

  private func setupCollectionViewLayout(_ collectionView: UICollectionView) {
    NSLayoutConstraint.activate([
      collectionView.leadingAnchor
        .constraint(equalTo: contentView.leadingAnchor),
      collectionView.trailingAnchor
        .constraint(equalTo: contentView.trailingAnchor),
      collectionView.topAnchor
        .constraint(equalTo: contentView.topAnchor),
      collectionView.bottomAnchor
        .constraint(equalTo: contentView.bottomAnchor),
    ])
  }
}

setupCollectionViewLayout只需启用 AutoLayout。 collectionView稍后将添加 tableViewCell实例出队。

class CollectionViewCell: UICollectionViewCell {}

class ViewController: UIViewController {

  private var lastSelectedCollectionViewCell: CollectionViewCell?

  private lazy var tableView: UITableView = {
    let tableView = UITableView()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell")
    return tableView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    view.addSubview(tableView)
    setupTableViewLayout(tableView)
  }

  private func setupTableViewLayout(_ tableView: UITableView) {
    NSLayoutConstraint.activate([
      tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
      tableView.topAnchor.constraint(equalTo: view.topAnchor),
      tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
    ])
  }
}

tableView在加载 View 时添加,并通过 setupTableViewLayout 添加 AutoLayout 约束. 请注意,您保留了最后一个索引路径的副本,但我认为保留对单元格本身的引用更好、更简单。

UITableViewDataSource扩展名:

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(
      withIdentifier: "cell",
      for: indexPath) as! TableViewCell

    guard cell.collectionView == nil else { return cell }

    let collectionView = UICollectionView(
      frame: .zero,
      collectionViewLayout: UICollectionViewFlowLayout())

    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "cell")

    cell.collectionView = collectionView

    return cell
  }
}

extension ViewController: UITableViewDelegate {}

我添加一个 collectionView 仅当它不存在于 tableViewCell 中. collectionView分配 dataSourcedelegate作为self ,尽管如果有一个额外的 modelController 对象会更好。 UITableViewDelegate是空的。

现在扩展为 collectionView小号:

extension ViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    cell.backgroundColor = .gray
    return cell
  }
}

extension ViewController: UICollectionViewDelegate {
  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    lastSelectedCollectionViewCell?.backgroundColor = .gray
    if let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell {
      cell.backgroundColor = .yellow
      lastSelectedCollectionViewCell = cell
    }
  }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 20, height: 20)
  }
}

重要的部分是collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) ,其他的只是样板代码。 选择 collectionViewCell 时,self.lastSelectedCollectionViewCell的颜色变回灰色,新选择的单元格分配给 lastSelectedCollectionViewCell , 在其 backgroundColor 之后改变了。

以下是您可以在 Playground 中运行的完整代码:

import UIKit
import PlaygroundSupport

class TableViewCell: UITableViewCell {
  var collectionView: UICollectionView? {
    didSet {
      guard let collectionView = collectionView else { return }
      contentView.addSubview(collectionView)
      collectionView.translatesAutoresizingMaskIntoConstraints = false
      collectionView.backgroundColor = .white
      setupCollectionViewLayout(collectionView)
    }
  }

  private func setupCollectionViewLayout(_ collectionView: UICollectionView) {
    NSLayoutConstraint.activate([
      collectionView.leadingAnchor
        .constraint(equalTo: contentView.leadingAnchor),
      collectionView.trailingAnchor
        .constraint(equalTo: contentView.trailingAnchor),
      collectionView.topAnchor
        .constraint(equalTo: contentView.topAnchor),
      collectionView.bottomAnchor
        .constraint(equalTo: contentView.bottomAnchor),
    ])
  }
}

class CollectionViewCell: UICollectionViewCell {}

class ViewController: UIViewController {

  private var lastSelectedCollectionViewCell: CollectionViewCell?

  private lazy var tableView: UITableView = {
    let tableView = UITableView()
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(TableViewCell.self, forCellReuseIdentifier: "cell")
    return tableView
  }()

  override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .white
    view.addSubview(tableView)
    setupTableViewLayout(tableView)
  }

  private func setupTableViewLayout(_ tableView: UITableView) {
    NSLayoutConstraint.activate([
      tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
      tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
      tableView.topAnchor.constraint(equalTo: view.topAnchor),
      tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
    ])
  }
}

extension ViewController: UITableViewDataSource {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 10
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(
      withIdentifier: "cell",
      for: indexPath) as! TableViewCell

    guard cell.collectionView == nil else { return cell }

    let collectionView = UICollectionView(
      frame: .zero,
      collectionViewLayout: UICollectionViewFlowLayout())

    collectionView.dataSource = self
    collectionView.delegate = self
    collectionView.register(CollectionViewCell.self, forCellWithReuseIdentifier: "cell")

    cell.collectionView = collectionView

    return cell
  }
}

extension ViewController: UITableViewDelegate {}

extension ViewController: UICollectionViewDataSource {
  func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return 10
  }

  func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
    cell.backgroundColor = .gray
    return cell
  }
}

extension ViewController: UICollectionViewDelegate {
  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    lastSelectedCollectionViewCell?.backgroundColor = .gray
    if let cell = collectionView.cellForItem(at: indexPath) as? CollectionViewCell {
      cell.backgroundColor = .yellow
      lastSelectedCollectionViewCell = cell
    }
  }
}

extension ViewController: UICollectionViewDelegateFlowLayout {
  func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 20, height: 20)
  }
}


PlaygroundPage.current.liveView = ViewController()

关于ios - collectionView didSelectItemAt superview 没有选择正确的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57632525/

相关文章:

ios - I/O操作性能

iphone - 尝试调整 UITableView 的大小会导致屏幕出现一秒钟的故障,然后才能正确显示

ios - 获取 UIPickerView Xcode Swift 中所选组件的索引

ios - 从设备获取所有图像并将其显示在 uicollectionview 中

ios - 带参数的 Swift 传递闭包

ios - 使用 iOS Objective C 访问 Web 服务并发送数据

swift - 如何避免强制展开变量?

ios - 带有部分和搜索字段的 UITableView

ios - 从解析中下载图像并在 UICollectionView 中显示

swift - 根据图像高度获取 Collection View 自定义布局中单元格的高度