Swift:UICollectionView 选择单元格 indexPath 问题 [英] Swift: UICollectionView selecting cell indexPath issues

查看:43
本文介绍了Swift:UICollectionView 选择单元格 indexPath 问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试做一个 Collection View,其中有人选择一个 cell 并且对于每个选择,它会将它们带到另一个 View Controller 保存选择的内容.但是,当我将这行代码应用于 didSelectItemAtIndexPath 时,我遇到了困难;

I am trying to do a Collection View whereby someone selects a cell and for each selection it takes them to another View Controller that holds content of the selection. However I'm running into difficulties as once I apply this line of code to didSelectItemAtIndexPath;

self.performSegueWithIdentifer("showDetail", sender: self)

然后在模拟器中运行它 cell 选择根据 indexPath 工作,但是每次我选择新的 cell 时它都会记住这些选择.例如,每个 cell 都有一张照片和标签,如果我选择 indexPath 中的第一个 cellsegue首先带我到空白视图,然后到我选择的 cell.如果我选择另一个 cellindexPath 上的数字 3,空白视图现在是我之前选择的第一个 cell选择第三个 cell .它每次都这样做.如果我删除 performSegueWithIdentifer 代码(来自 Xcode 6.2(在 6.1.1 中它是随机的)),则选择是我之前的选择,而不是我的selectedCell",但至少它只选择一次而不是两次进入view.indexPath 出现问题.这是我的 prepareForSegue

and then run it in the Simulator the cell selection is working according the indexPath but its remembering the selections each time I select new cell. So for example each cell has a photo and label and if I select the first cell in the indexPath the segue takes me first to blank view and then to my selected cell. If I select another cell, number 3 on the indexPath the blank view is now the first cell from my previous choice after which it takes to my selected third cell . Its doing that every time. If I remove the performSegueWithIdentifer code (from Xcode 6.2 (in 6.1.1 it was random)) the selection is my previous choice and never my 'selectedCell', but then at least its only selecting once instead of twice to get to a view. There is something going wrong on the indexPath. This is the code for my prepareForSegue

override func prepareForSegue(segue: UIStoryBoardSegue, sender: AnyObject?) {
      if segue.identifer == "showDetail" {
          let detailVC:DetailViewController = segue.destinationViewController as DetailViewController
             detailVC.selectedImageName = selectedImage
             detailVC.selectedLabel = selectedLabels
             }
      }

我被困在做什么 &应用什么解决方案.我是否保留 performSegueWithIdentifer 代码 &创建一个 Equatable 以在 indexPath 上实现 find(array, selection)?或者我可以编写一个循环(这似乎更容易),它会根据选择运行 indexPath 并删除不再选择的单元格.但是,我不确定要在循环中写入什么条件,因为我不知道selectedCell"属性的值,因为它是可选的.

I'm stuck on what to do & what solution to apply. Do I keep performSegueWithIdentifer code & create an Equatable to implement find(array, selection) on the indexPath? Or could I write a loop, (which seems much easier), that would run through the indexPath based upon the selections and that would remove the cell that is no longer selected. However I'm not sure what condition to write in the loop because I don't know the value of the property of the 'selectedCell' because its optional.

for (index, value) in enumerate(cellItems) {
//something here to remove 'selectedItem' in the indexPath
}

如果我从 didSelectItemAtIndexPath 中删除了 performSegueWithIdentifer 代码,我可以在我的 prepareForSegue 中做什么来获得正确索引路径上的选择?

If I remove performSegueWithIdentifer code from didSelectItemAtIndexPath what can I do in my prepareForSegue to get the selection on the correct indexPath?

didSelectItemAtIndexPath

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
     selectedImage = cellImages[indexPath.row] as String
     selectedLabels = cellLabels[indexPath.row] as String
     self.performSegueWithIdentifer("showDetail", sender: self)
   }

我已经尝试将 performSegueWithIdentifer 中的 sender 更改为 indexPath 但问题仍然存在.

I've tried changing sender in the performSegueWithIdentifer to indexPath but the problem still remains.

编辑 2 完整代码到我的 CollectionViewController

EDIT 2 Complete code to my CollectionViewController

class CollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate {

@IBOutlet weak var collectionView: UICollectionView!

var selectedImage = String()
var selectedLabels = String()

var cellImages:[String] = ["1.jpg", "2.jpg", "3.jpg", "4.jpg", "5.jpg", "6.jpg", "7.jpg", "8.jpg", "9.jpg", "10.jpg", "11.jpg", "13.jpg", "14jpg"]

var cellLabels:[String] = ["Photo 1", "Photo 2", "Photo 3", "Photo 4", "Photo 5", "Photo 6", "Photo 7", "Photo 8", "Photo 9", "Photo 10", "Photo 11", "Photo 12", "Photo 13", "Photo 14"]

func collectionView(collectionView: UICollectionView, numberOfNumberItemsInSection: Int) -> Int {
    return cellImages.count
}

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    let cell: PhotoViewCell = collectionView.dequeueReuseableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as PhotoViewCell 
    cell.labelCell.text = cellLabels[indexPath.row]
    cell.ImageCell.image = UIImage(named: cellImages[indexPath.row])
    return cell
}

 override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
     selectedImage = cellImages[indexPath.row] as String
     selectedLabels = cellLabels[indexPath.row] as String
     self.performSegueWithIdentifer("showDetail", sender: self)
   }

override func prepareForSegue(segue: UIStoryBoardSegue, sender: AnyObject?) {
      if segue.identifer == "showDetail" {
          let detailVC:DetailViewController = segue.destinationViewController as DetailViewController
          detailVC.selectedImageName = selectedImage
          detailVC.selectedLabel = selectedLabels
          }
      }
}

PhotoViewCell

PhotoViewCell

class PhotoViewCell: UICollectionViewCell {

@IBOutlet var labelCell: UILabel!
@IBOutlet var ImageCell: UIImage!

}

编辑 3 - 修正

我尝试了您的建议,但不幸的是,双重视图仍然存在问题 - 在将我带到实际选定的 cell 之前,它仍在传递两个视图.我还在 didSelectItemAtIndexPath 中稍微修改了代码,但它仍然没有解决问题.

I tried your suggestion and unfortunately the problem is still persisting on double views - it's still passing two views before it takes me to the actual selected cell. I also amended the code slightly in the didSelectItemAtIndexPath but it still didn't fix the problem.

if let cell = collectionView.cellForItemAtIndexPath(indexPath) as? PhotoViewCell {

performSegueWithIdentifier("showDetail", sender: cell) 
}

但是按照您的其他建议,在我的 StoryBoard 中,我从我的 Collection View cell 添加了一个 segue到我的 DetailViewController,它具有标识符showDetail".如果我删除 segue,则无法从我的 cells 中选择任何内容.

However following your other suggestion, in my StoryBoard I have added a segue from my Collection View cell to my DetailViewController, which has the identifier "showDetail". If I remove segue nothing can be selected from my cells.

虽然看起来 performSegueWithIdentifer 代码是双视图的触发器,因为当我删除它时,cell 只被选中一次,问题是 <cell 选择的 code>indexPath 不正确,因为它首先在空白视图上进行选择(是否与 showDetail segue 相关?)然后使我的 indexPath 不同步.

Although it seems the performSegueWithIdentifer code is the trigger for the double views because when I remove it, the cell is only being selected once, the problem was that the indexPath of the cell selection was not correct, because it's first selecting on a blank view (is that to do with the showDetail segue?), which then puts my indexPath out of sync.

编辑 - 已解决

这停止了双重选择(删除了 performSegueWithIdentifier 行):-

This stopped the double selections (the performSegueWithIdentifier line was removed): -

override func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
if let cell = collectionView.cellForItemAtIndexPath(indexPath) {
cellLabels[indexPath.row] as String
cellImages[indexPath.row] as String
   }
}

非常感谢您的帮助!!!!

Many Thanks for your help !!!!

推荐答案

(注意:我为 Swift 4 和更现代的实践更新了这个.)

(NOTE: I updated this for Swift 4 and more modern practices.)

我尽可能多地使用 UIView 对象.

I stick to UIView objects as much as possible.

override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    guard let cell = collectionView.cellForItem(at: indexPath) else { return }

    performSegue(withIdentifier: "showDetail", sender: cell)
}

然后在prepare(for:sender:)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    switch segue.identifier {
    case "showDetail":
        guard let indexPath = (sender as? UIView)?.findCollectionViewIndexPath() else { return }
        guard let detailViewController = segue.destination as? DetailViewController else { return }

        detailViewController.selectedImageName = cellImages[indexPath.row]
        detailViewController.selectedLabel = cellLabels[indexPath.row]

    default: return
    }
}

<小时>

我使用了我不久前创建的扩展 findCollectionViewIndexPath()

extension UIView {

    func findCollectionView() -> UICollectionView? {
        if let collectionView = self as? UICollectionView {
            return collectionView
        } else {
            return superview?.findCollectionView()
        }
    }

    func findCollectionViewCell() -> UICollectionViewCell? {
        if let cell = self as? UICollectionViewCell {
            return cell
        } else {
            return superview?.findCollectionViewCell()
        }
    }

    func findCollectionViewIndexPath() -> IndexPath? {
        guard let cell = findCollectionViewCell(), let collectionView = cell.findCollectionView() else { return nil }

        return collectionView.indexPath(for: cell)
    }

}

<小时>

我怀疑你在故事板中已经有一个 segue 并且不需要 func collectionView(, didSelectItemAtIndexPath:),但不管怎样,prepare segue 应该可以工作.


I have a suspicion that you have a segue in the storyboard already and don't need func collectionView(, didSelectItemAtIndexPath:), but either way, the prepare segue should work.

这篇关于Swift:UICollectionView 选择单元格 indexPath 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆