Search code examples
swiftcollectionview

How to reload a collectionview when I tap on back?


My collectionview did not reload when I tap back from the tableview where I the list reorder.

I have read a few topics but I don't know what's wrong. Can anybody find it?

And can I the speak part of the code place in an apart swift file and include this ViewController. So yes, how? Because I use that in more ViewControllers.

Below is my code.

Thank you very much.

import UIKit
import AVFoundation

class CollectionViewController: UICollectionViewController {

    @IBOutlet var soundBoard: UICollectionView!

    var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"]
    var bgColor = [""]

    var buttonOn: Bool = true

    override func viewDidLoad() {
        super.viewDidLoad()

        let blockItems = UserDefaults.standard.object(forKey:"soundboard")

        if(blockItems != nil) {
            list = blockItems as! [String]
        }

        let itemSize = UIScreen.main.bounds.width/2 - 2
        let itemHeight = itemSize / 2
        let layout = UICollectionViewFlowLayout()
        layout.sectionInset = UIEdgeInsetsMake(3, 0, 3, 0)
        layout.itemSize = CGSize(width: itemSize, height: itemHeight)

        layout.minimumInteritemSpacing = 3
        layout.minimumLineSpacing = 3

        soundBoard.collectionViewLayout = layout
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(true)

        self.collectionView!.reloadData()
    }

    // MARK: - Collection View

    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of items

        return list.count
    }


    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> MyCollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MyCollectionViewCell

        cell.cellTitle.text = list[indexPath.row]

        return cell
    }

    override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

        Speak(currentTitle: list[indexPath.row])
    }


    // MARK: - Speak function


    let synth = AVSpeechSynthesizer()
    var myUtterance = AVSpeechUtterance(string: "")

    func Speak(currentTitle: String) {

        if !synth.isSpeaking {
            // Controleert volume
            let volume = AVAudioSession.sharedInstance().outputVolume

            if volume < 0.5 {
                MuteButton()
            }

            // Spreekt de tekst uit
            let myUtterance = AVSpeechUtterance(string: currentTitle)
            myUtterance.rate = 0.4
            myUtterance.volume = 1

            if let theVoice = UserDefaults.standard.object(forKey:"voice") {
                myUtterance.voice = AVSpeechSynthesisVoice(language: theVoice as? String)
            }

            synth.speak(myUtterance)
        }
    }


    func MuteButton() {

        let alertController = UIAlertController(title: "Check your volume", message:
            "Please check your volume or mute button.", preferredStyle: UIAlertControllerStyle.alert)
        alertController.addAction(UIAlertAction(title: "Close", style: UIAlertActionStyle.default,handler: nil))

        self.present(alertController, animated: true, completion: nil)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: -- Save UserDefaults 

    func save() {
        UserDefaults.standard.set(self.list, forKey:"soundboard")
        UserDefaults.standard.synchronize()

        self.collectionView?.reloadData()
    }


    // MARK: -- Add new sound item

    @IBAction func addNew(_ sender: Any) {

        let alertController = UIAlertController(title: "Create a new sound", message: "", preferredStyle: UIAlertControllerStyle.alert)

            alertController.addTextField { (textField: UITextField) in
                textField.keyboardAppearance = .dark
                textField.keyboardType = .default
                textField.autocorrectionType = .default
                textField.placeholder = "Type something here"
                textField.clearButtonMode = .whileEditing
            }


        alertController.addAction(UIAlertAction(title: "Create", style: .default) { [weak alertController] _ in
            if let alertController = alertController {
                let loginTextField = alertController.textFields![0] as UITextField

                self.list.append( loginTextField.text!)

                self.save()
            }
        })


        alertController.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.default,handler: nil))

        self.present(alertController, animated: true, completion: nil)
    }
}

Solution

  • Two things are happening here. First you appear to have two different collection views in CollectionViewController; collectionView which is inherited from the superclass and soundboard which you declare. In viewWillAppear you tell collectionView to reload. If this is not the one that is hooked up in IB nothing will work.

    The second issue is that while in soundboardTableViewController you update the user default with the correct data you never read it after the view loads in CollectionViewController.

    You should move this:

    let blockItems = UserDefaults.standard.object(forKey:"soundboard")
    if(blockItems != nil) {
       list = blockItems as! [String]
    }
    

    into viewWillAppear before your call to reload the collection view and then verify you are telling the right collection view to reload.