Ios 点击UICollectionView中的单元格返回错误的索引

Ios 点击UICollectionView中的单元格返回错误的索引,ios,swift,xcode,uicollectionview,Ios,Swift,Xcode,Uicollectionview,我真的不知道我错过了什么。我已经设置了UICollectionView并且内容设置正确。cellForItemAt部分如下所示: func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdent

我真的不知道我错过了什么。我已经设置了
UICollectionView
并且内容设置正确。
cellForItemAt
部分如下所示:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DetailsEventImageCell", for: indexPath) as? DetailsEventImageCell
    
    print("Loaded - IndexPathItem: \(indexPath.item)")
    
    cell?.backgroundColor = .clear
    cell?.contentView.layer.cornerRadius = 10
    cell?.contentView.layer.masksToBounds = true
    cell?.eventImage.image = images[indexPath.row]
    
    return cell ?? UICollectionViewCell()
}
collectionView
正确显示单元格,但问题出在这里。当我进入编辑模式并随机点击所有单元格时,有时它会返回错误的索引并标记错误的单元格(主要是在其旁边),如下图所示:

由于单元格设置正确,我不知道为什么它偶尔会为所选单元格返回错误的
indexPath
。如果我点击一个单元格两次,它会突然返回正确的
indepath
。如果我取消选择所有单元格并重试,则有些单元格会再次返回错误的
indepath

这是我的
didSelectItemAt
code

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    print(indexPath.item)
    if isEditing {
        if let cell = collectionView.cellForItem(at: indexPath) as? DetailsEventImageCell {
            cell.isInEditingMode = isEditing
            cell.isSelected = true
        }
    }
}
以下两个函数也可能是罪魁祸首,但我不明白为什么它会正确设置
collectionView
,然后点击返回错误的值

这是我的自定义单元格:

class DetailsEventImageCell: UICollectionViewCell {

@IBOutlet weak var eventImage: UIImageView!
@IBOutlet weak var selectedForDeletionImage: UIImageView!

var isInEditingMode: Bool = false {
    didSet {
        if !isInEditingMode {
            //selectedForDeletionImage.isHidden = true
            isSelected = false
        }
    }
}

override var isSelected: Bool {
    didSet {
        if isInEditingMode {
            selectedForDeletionImage.isHidden = isSelected ? false : true
        }
    }
}
这是我的
setEditing
code

override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)
        
        collectionView.allowsMultipleSelection = editing
        
        //Deselect all selected cells
        if !editing {
            if let indexPaths = collectionView.indexPathsForSelectedItems {
                for indexPath in indexPaths {
                    self.collectionView.deselectItem(at: indexPath, animated: false)
                }
            }
        }
        
        
        let indexPaths = collectionView.indexPathsForVisibleItems
        for indexPath in indexPaths {
            if let cell = collectionView.cellForItem(at: indexPath) as? DetailsEventImageCell {
                cell.isInEditingMode = editing
            }
        }
    }

我希望有人能帮我解决这个问题。

经过几个小时的尝试,我发现这似乎是一个与iOS模拟器相关的问题。我不能访问所有大小的设备,所以我有时会使用它进行快速测试

在模拟器中“缓慢地”点击单元格确实能像预期的那样工作,但是如果我在单元格内点击过快,它似乎无法跟上并再次选择上一个单元格

在实际的设备上,可以以任何速度点击电池,并按预期工作

编辑:这个问题似乎只出现在2012年底XCode 11.7上我的Mac Mini(macOS Catalina 10.15.6)上的iOS模拟器上
我的Macbook Pro 15“2019和我试过的所有硬件设备(iPhone 11 Pro、ipad Air、iPhone SE第二代)在相同的项目和相同的OS/XCode构建下都能正常工作。

我认为如果你有很多电池,上述实现将无法工作,因为电池是可重用的

  • 您可以在数组中收集选定的索引路径,在每个didSelece/didselect方法上重新加载

  • 在CellForRowaItem方法中执行UI更新

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {   
        if isEditing {
           self.selectedIndexPaths.append(indexPath)
           self.collectionView.reloadData()
        }
    }
    
  • 在DIDDENSELECT中,方法将类似于

    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        if let index = self.selectedIndexPaths.firstIndex(of: indexPath) {
            self.selectedIndexPaths.remove(at: index)
        }
        self.collectionView.reloadData()
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DetailsEventImageCell", for: indexPath) as? DetailsEventImageCell
    
    print("Loaded - IndexPathItem: \(indexPath.item)")
    
    cell?.backgroundColor = .clear
    cell?.contentView.layer.cornerRadius = 10
    cell?.contentView.layer.masksToBounds = true
    cell?.eventImage.image = images[indexPath.row]
    if self.selectedIndexpaths.contains(indexPath) {
       cell.isSelected = true
    } else {
       cell.isSelected = false
    }
    return cell ?? UICollectionViewCell()
    
    最后,CellforRowaItem将像

    func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
        if let index = self.selectedIndexPaths.firstIndex(of: indexPath) {
            self.selectedIndexPaths.remove(at: index)
        }
        self.collectionView.reloadData()
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "DetailsEventImageCell", for: indexPath) as? DetailsEventImageCell
    
    print("Loaded - IndexPathItem: \(indexPath.item)")
    
    cell?.backgroundColor = .clear
    cell?.contentView.layer.cornerRadius = 10
    cell?.contentView.layer.masksToBounds = true
    cell?.eventImage.image = images[indexPath.row]
    if self.selectedIndexpaths.contains(indexPath) {
       cell.isSelected = true
    } else {
       cell.isSelected = false
    }
    return cell ?? UICollectionViewCell()
    

    }

    单元格已正确初始化和重用。当单元格被重用并更新数据时,我进行了调试打印。如上所述,数据也正确显示。当我在编辑模式之外点击单元格时,它们总是返回正确的indexPath。当我进入编辑模式并快速连续选择多个单元格时,它将被删除偶尔返回错误的indexPath。当我只显示5个单元格,并且没有单元格从视图中消失或重新出现以供重用时,也会发生这种情况。问题仍然存在于模拟器中,在设备上,它总是按预期工作,并且总是返回正确的值。好吧,我对此并不武断。但我对这个问题很武断我认为直接修改单元格而不是修改源数据并将其导入接口是错误的。如果您可以制作一个非常小的测试项目来演示这个问题,也许我可以下载它(例如从github下载)并尝试一下。你必须明白,我多年来一直在为选定的州制作收集视图,从未见过这个问题;你一定想知道这是为什么。我知道你的意思,也许我的措辞是错误的,因为我不是英语母语。我所做的基本上是修改collectionView和在加载/重用特定单元格时,将正确的数据(图像)签名到这些单元格。我已将imageView添加到单元格中,以便在单元格状态为“isSelected”时显示,在isSelected状态为false时不显示。我没有修改源数据(图像)从委托方法内部。很高兴你能提供帮助,但你的回答可能会有点自大,因为很明显我是新来的。我不怀疑你比我有更多的经验,我实际上是为了好玩而为iOS编程,但我多年来从未在任何collectionView或tableView上遇到过这个问题(在我初次尝试之后)。我在两台iPad和3台不同的iPhone上尝试了该代码,它总是准确地返回到我期望的控制台。唯一一次失败是在我尝试使用iOS模拟器时。我使用的Mac Mini现在已经7年了,它已经不是最快的了,所以它可能实际上要对这种行为负责。谢谢你的回答。严重问题:将选定的索引路径存储在var中与使用collectionView.indexPathsForSelectedItems之间有什么区别?即使在使用100多个单元格进行测试并到处选择时,该变量似乎始终存储正确的索引路径。可能是操作系统、设备或性能等方面的问题。对我来说,它工作正常正如我在回答中所说的那样,我在实际的硬件设备上进行了测试。似乎只有在模拟器中才会出现问题。我的Mac电脑很旧,所以它实际上可能是一个性能问题。尽管有人说“不”,但还是否决了我。非常感谢你的帮助!祝你度过愉快的一天