Swift:UICollectionView 选择单元格 indexPath 问题 [英] Swift: UICollectionView selecting cell indexPath issues
问题描述
我正在尝试做一个 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
中的第一个 cell
,segue
首先带我到空白视图,然后到我选择的 cell
.如果我选择另一个 cell
,indexPath
上的数字 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屋!