CollectionView reloadData() 奇怪的行为

CollectionView reloadData() weird behaviour

我想制作一个 Collection 带有单元格的视图,您可以在其中 select 我的小游戏的颜色。因此,您可以在不同的主题之间进行选择(每个主题都在一个单元格中)。如果主题被解锁(通过获得分数),模糊视图和 lock-icon 应该消失,并且所有可用的单元格/主题应该 select 可用。我是这样实现的:

(Collection ViewController Class:)

    import UIKit
import PMSuperButton

class myCollectionViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {

    @IBOutlet weak var backBtn: UIButton!
    
    let items = ["Default dot", "Trap your first dot", "Score 15 or less (classic)", "Score 5 or less (classic)", "Score 15 or less (hard)", "Score 25 or less (no chill)", "Score 15 or less (snake)", "Score 15 or less everywhere", "Score 10 or less everywhere", "Circle the dot 100 times", "10"]
    var preSelected = IndexPath()
    
    @IBOutlet weak var myCollectionView: UICollectionView!
    override func viewDidLoad() {
        super.viewDidLoad()
        updateUnlockedString()
        updateColor()
    }
    
    func updateColor(){
        view.backgroundColor = myColors().selected(value: selectedInstance.selectedColor).backgroundColor
    }
    func   updateUnlockedString(){
        let easyHS = UserDefaults.standard.integer(forKey: "highscoreeasy")
        let classicHS = UserDefaults.standard.integer(forKey: "highscoreclassic")
        let hardHS = UserDefaults.standard.integer(forKey: "highscorehard")
        let nochillHS = UserDefaults.standard.integer(forKey: "highscoreno chill")
        let snakeHS = UserDefaults.standard.integer(forKey: "highscoresnake")
        
        var unlockedString = ""
        
        //unimportant steps deleted

        UserDefaults.standard.set(unlockedString, forKey: "unlocked")
        
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return items.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! myCollectionViewCell
        if(unlockInstance.unlockedString.contains(String(indexPath.item))){
            cell.unlockedEffect()
            print("unlocked Effect")
        }
        cell.label.text = items[indexPath.item]
        cell.removeHighlight()
        if indexPath.item == selectedInstance.selectedColor{
             cell.highlightEffect()
             preSelected = IndexPath(item: indexPath.item, section: indexPath.section)
         }
        cell.setupCellFilling(playerColor: myColors().selected(value: indexPath.item).playerColor, objColor: myColors().selected(value: indexPath.item).objColor, defaultColor: myColors().selected(value: indexPath.item).defaultColor, backgroundColor: myColors().selected(value: indexPath.item).backgroundColor)
         myCollectionView = collectionView
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        collectionView.allowsMultipleSelection = false
        if ((collectionView.cellForItem(at: indexPath) as! myCollectionViewCell?) != nil) && unlockInstance.unlockedString.contains(String(indexPath.item)){
            selectedInstance.selectedColor = indexPath.item
            updateColor()
            collectionView.reloadData()
        }
    }
    @IBAction func backPressed(_ sender: Any) {
        cameInstance.came = true
    }
    
}

(Collection 细胞 Class:)

    import UIKit

class myCollectionViewCell: UICollectionViewCell {
    
    @IBOutlet weak var label: UILabel!
    @IBOutlet weak var view: UIView!
    @IBOutlet weak var blurView: UIVisualEffectView!
    @IBOutlet weak var lockedBlur: UIVisualEffectView!
    @IBOutlet weak var lockedIcon: UIImageView!

    override func layoutSubviews() {
        // cell rounded section
        self.layer.cornerRadius = 15.0
        self.layer.masksToBounds = true
        
        // cell shadow section
        self.contentView.layer.cornerRadius = 15.0
        self.contentView.layer.masksToBounds = true
        self.layer.shadowColor = myColors().selected(value: selectedInstance.selectedColor).defaultColor.cgColor
        self.layer.shadowOffset = CGSize(width: 0.0, height: 0.0)
        self.layer.shadowRadius = 6.0
        self.layer.shadowOpacity = 0.4
        self.layer.cornerRadius = 15.0
        self.layer.masksToBounds = false
        self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.contentView.layer.cornerRadius).cgPath
        super.layoutSubviews()
    }
   

extension myCollectionViewCell{

   func highlightEffect(){
      self.layer.borderWidth = 5.0
      self.layer.borderColor = UIColor.systemGreen.cgColor
   }

   func removeHighlight(){
      self.layer.borderColor = UIColor.clear.cgColor
   }
    func unlockedEffect(){
        lockedBlur.alpha = 0
        lockedIcon.alpha = 0
    }
    func setupCellFilling(playerColor: UIColor, objColor: UIColor, defaultColor: UIColor, backgroundColor: UIColor){
        
        lockedBlur.effect = UIBlurEffect(style: .extraLight)
        blurView.effect = UIBlurEffect(style: .systemUltraThinMaterialDark)
        lockedIcon.tintColor = objColor
        view.backgroundColor = backgroundColor
  
    }

}

问题

当我打开 CollectionView (viewDidLoad) 时,一切都 100% 正常!所有应锁定的单元格都显示为已锁定(lockedBlur.alpha = 0 和 lockedIcon.alpha = 0)。此外,只有锁定的单元格是 select 可用的,我可以用绿色边框看到。只有 selected Cell 有绿色边框,没错。

但是:当我 select 一个单元格时, 一些随机锁定的单元格松开它们的模糊视图并松开它们的 lock-icon(因此 blockedBlur 和 lockedIcon 消失) .他们仍然无法 select。有时这会影响所有细胞,有时只会影响例如细胞。 2.

当我 select 一个单元格时,会调用 didSelectItemAt 函数。这也调用了 updateColors(),它只改变背景并调用神秘的 reloadData()。在我看来,reloadData() 以某种方式使 lockedBlur 和 lockedIcon 消失,我找不到原因....

也许有人可以帮助我..

谢谢!!

SwiftHobby

我正在开发 Fitness App,它的训练计划部分具有非常相似的工作 CollectionView 行为。基本上你 select 完成练习后的某个单元格。因此,我尝试了很多实现 selecting 和 deselecting 单元格的方法。如我所见,您缺少 CollectionViewDelegate 的 selecting 和 deselecting 函数。在那里你设置不同的状态 Effects

以下是您必须使用的函数:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    if let cell = collectionView.cellForItem(at: indexPath) as? CustomCollectionViewCell {
        cell.showIcon()
    }
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    if let cell = collectionView.cellForItem(at: indexPath) as? CustomCollectionViewCell {
        cell.hideIcon()
    }
}