CollectionView reloadData() странное поведение

#ios #swift #xcode #uicollectionview #uicollectionviewcell

#iOS #swift #xcode #uicollectionview #uicollectionviewcell

Вопрос:

Я хочу создать представление коллекции с ячейками, где вы можете выбирать цвета моей маленькой игры. Для этого вы можете выбирать между разными темами (каждая в одной ячейке). Если тема разблокирована (при достижении результатов), вид размытия и значок блокировки должны исчезнуть, и все доступные ячейки / темы должны быть доступны для выбора. Я реализовал это следующим образом:

(Класс ViewController коллекции:)

     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) amp;amp; unlockInstance.unlockedString.contains(String(indexPath.item)){
            selectedInstance.selectedColor = indexPath.item
            updateColor()
            collectionView.reloadData()
        }
    }
    @IBAction func backPressed(_ sender: Any) {
        cameInstance.came = true
    }
    
}
  

(Класс ячейки коллекции:)

     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). Кроме того, выбираются только заблокированные ячейки, которые я вижу с зеленой рамкой. Только выбранная ячейка имеет зеленую рамку, это верно.

НО: когда я выбираю ячейку, некоторые случайные заблокированные ячейки теряют свой размытый вид и теряют значок блокировки (поэтому blockedBlur и lockedIcon исчезают). Они по-прежнему не выбираются. Иногда это затрагивает все ячейки, иногда только, например, 2.

Когда я выбираю ячейку, вызывается функция didSelectItemAt . И это также вызывает UpdateColors(), который только изменяет фон и вызывает таинственный reloadData() . На мой взгляд, reloadData() КАКИМ-ТО ОБРАЗОМ заставляет lockedBlur и lockedIcon исчезать, и я не могу найти почему….

Может быть, кто-нибудь может мне помочь..

Спасибо!!

SwiftHobby

Ответ №1:

Я работаю над фитнес-приложением, которое имеет довольно похожее рабочее поведение CollectionView для раздела плана тренировок. По сути, вы выбираете определенную ячейку, когда заканчиваете упражнение. Итак, я много играл со способом реализации выбора и отмены выбора ячеек. Как я вижу, вам не хватает функций выбора и отмены выбора CollectionViewDelegate . Там вы устанавливаете разные эффекты состояний

Вот функции, которые вы должны использовать:

 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()
    }
}