当水平滚动集合视图时,如何确定选择哪个tableView单元格

时间:2022-10-04 11:42:55

I have collectionView inside TableViewCell. TableView has 1 section and 4 rows.

我在TableViewCell中有collectionView。 TableView有1个部分和4个行。

I want to figure out which row of tableviewcell is selected when collectionView is Scrolled Horizontally.

我想弄清楚当collectionView水平滚动时选择了哪一行tableviewcell。

I tryed to figure out by putting tableView row in "var nowRow" variable like below code. But It does not work.

我试着把tableView行放在“var nowRow”变量中,就像下面的代码一样。但它不起作用。

How can I find out which row of tableviewcell is selected?

如何找出选择哪一行tableviewcell?

class Home2ViewController: UIViewController, UITableViewDataSource,  UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {

    var posts = [Post]()
    var nowRow = Int()

    override func viewDidLoad() {
        // get posts elements here 
        //posts.append(element).......
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

            return posts.count // 4counts 

    }

    func numberOfSections(in tableView: UITableView) -> Int {

        return 1
    }

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

        nowRow = indexPath.row

        cell.post = posts[nowRow]
        cell.collectionView1.delegate = self
        cell.collectionView1.dataSource = self

        cell.collectionView1.reloadData()
        return cell
    }



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

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return posts[nowRow].imageUrls.count
    }

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

        let photoUrlString = posts[nowRow].imageUrls[indexPath.item] // ←error occured
            let photoUrl = URL(string: photoUrlString)
            cell.imageView1.sd_setImage(with: photoUrl)


        return cell
    }
}

editeditedit

1 个解决方案

#1


0  

As you have no doubt discovered, interacting with the collectionViews in your table rows does not trigger the tableView method tableView(_:didSelectRowAt:), and tableView.indexPathForSelectedRow is nil because no row has been selected. You need a way to map from the collectionView to the indexPath.row that contains it. This information is known at tableViewCell setup time.

毫无疑问,发现与表行中的collectionViews交互不会触发tableView方法tableView(_:didSelectRowAt :),并且tableView.indexPathForSelectedRow为nil,因为没有选择任何行。您需要一种从collectionView映射到包含它的indexPath.row的方法。此信息在tableViewCell设置时已知。

Add a dictionary to your Home2ViewController that maps a UICollectionView to a row Int:

在Home2ViewController中添加一个字典,将UICollectionView映射到行Int:

var collectionViewRow = [UICollectionView : Int]()

Add the entries in tableView(_:cellForRowAt:) where you know the row and collectionView:

在tableView(_:cellForRowAt :)中添加条目,您知道row和collectionView:

collectionViewRow[cell.collectionView1] = indexPath.row

Then, anytime you have a collectionView, you can look up its row:

然后,只要你有一个collectionView,你就可以查找它的行:

let row = collectionViewRow[collectionView]!

Here's the whole code:

这是整个代码:

class Home2ViewController: UIViewController, UITableViewDataSource,  UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {

    var posts = [Post]()
    var collectionViewRow = [UICollectionView : Int]()

    override func viewDidLoad() {
        // get posts elements here
        //posts.append(element).......
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return posts.count // 4counts
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

        collectionViewRow[cell.collectionView1] = indexPath.row

        cell.post = posts[indexPath.row]
        cell.collectionView1.delegate = self
        cell.collectionView1.dataSource = self

        cell.collectionView1.reloadData()
        return cell
    }

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

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let row = collectionViewRow[collectionView]!
        return posts[row].imageUrls.count
    }

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

        let row = collectionViewRow[collectionView]!
        let photoUrlString = posts[row].imageUrls[indexPath.item] // ←error occured
        let photoUrl = URL(string: photoUrlString)
        cell.imageView1.sd_setImage(with: photoUrl)

        return cell
    }
}

Notes:

  1. The force unwrap of the dictionary lookup won't fail because the collectionView will be in there. If you want to unwrap it with if let, you'll need to decide what to do when you don't get a row (which shouldn't happen).
  2. 字典查找的强制解包不会失败,因为collectionView将在那里。如果你想用let打开它,你需要决定当你没有得到一行时该做什么(这不应该发生)。

  3. This method could fail if your table allows editing (user can rearrange order of rows or delete rows). If you don't support editing, then this will work fine. To support editing, you could change the dictionary to [UICollectionView : UITableViewCell]. Then, given a UICollectionView, you could look up its cell, and then call let indexPath = tableView.indexPath(for: cell) to get the indexPath and your row is then just indexPath.row.
  4. 如果您的表允许编辑(用户可以重新排列行的顺序或删除行),此方法可能会失败。如果你不支持编辑,那么这将正常工作。要支持编辑,您可以将字典更改为[UICollectionView:UITableViewCell]。然后,给定一个UICollectionView,你可以查找它的单元格,然后调用let indexPath = tableView.indexPath(for:cell)来获取indexPath,然后你的行只是indexPath.row。

#1


0  

As you have no doubt discovered, interacting with the collectionViews in your table rows does not trigger the tableView method tableView(_:didSelectRowAt:), and tableView.indexPathForSelectedRow is nil because no row has been selected. You need a way to map from the collectionView to the indexPath.row that contains it. This information is known at tableViewCell setup time.

毫无疑问,发现与表行中的collectionViews交互不会触发tableView方法tableView(_:didSelectRowAt :),并且tableView.indexPathForSelectedRow为nil,因为没有选择任何行。您需要一种从collectionView映射到包含它的indexPath.row的方法。此信息在tableViewCell设置时已知。

Add a dictionary to your Home2ViewController that maps a UICollectionView to a row Int:

在Home2ViewController中添加一个字典,将UICollectionView映射到行Int:

var collectionViewRow = [UICollectionView : Int]()

Add the entries in tableView(_:cellForRowAt:) where you know the row and collectionView:

在tableView(_:cellForRowAt :)中添加条目,您知道row和collectionView:

collectionViewRow[cell.collectionView1] = indexPath.row

Then, anytime you have a collectionView, you can look up its row:

然后,只要你有一个collectionView,你就可以查找它的行:

let row = collectionViewRow[collectionView]!

Here's the whole code:

这是整个代码:

class Home2ViewController: UIViewController, UITableViewDataSource,  UITableViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate {

    var posts = [Post]()
    var collectionViewRow = [UICollectionView : Int]()

    override func viewDidLoad() {
        // get posts elements here
        //posts.append(element).......
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return posts.count // 4counts
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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

        collectionViewRow[cell.collectionView1] = indexPath.row

        cell.post = posts[indexPath.row]
        cell.collectionView1.delegate = self
        cell.collectionView1.dataSource = self

        cell.collectionView1.reloadData()
        return cell
    }

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

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        let row = collectionViewRow[collectionView]!
        return posts[row].imageUrls.count
    }

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

        let row = collectionViewRow[collectionView]!
        let photoUrlString = posts[row].imageUrls[indexPath.item] // ←error occured
        let photoUrl = URL(string: photoUrlString)
        cell.imageView1.sd_setImage(with: photoUrl)

        return cell
    }
}

Notes:

  1. The force unwrap of the dictionary lookup won't fail because the collectionView will be in there. If you want to unwrap it with if let, you'll need to decide what to do when you don't get a row (which shouldn't happen).
  2. 字典查找的强制解包不会失败,因为collectionView将在那里。如果你想用let打开它,你需要决定当你没有得到一行时该做什么(这不应该发生)。

  3. This method could fail if your table allows editing (user can rearrange order of rows or delete rows). If you don't support editing, then this will work fine. To support editing, you could change the dictionary to [UICollectionView : UITableViewCell]. Then, given a UICollectionView, you could look up its cell, and then call let indexPath = tableView.indexPath(for: cell) to get the indexPath and your row is then just indexPath.row.
  4. 如果您的表允许编辑(用户可以重新排列行的顺序或删除行),此方法可能会失败。如果你不支持编辑,那么这将正常工作。要支持编辑,您可以将字典更改为[UICollectionView:UITableViewCell]。然后,给定一个UICollectionView,你可以查找它的单元格,然后调用let indexPath = tableView.indexPath(for:cell)来获取indexPath,然后你的行只是indexPath.row。