点击返回时如何重新加载集合视图?

How to reload a collectionview when I tap on back?

当我从列表重新排序的表视图中点击返回时,我的集合视图没有重新加载。

我已经阅读了一些主题,但我不知道哪里出了问题。有人能找到吗?

我能否将代码的 speak 部分放在单独的 swift 文件中并包含此 ViewController。所以是的,怎么样?因为我用了更多 ViewControllers.

下面是我的代码。

非常感谢。

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

我看到这里有一些可能出错的地方。但是,在另一个视图控制器中查看代码会有所帮助。

首先,您确定您正确地重新排序了您的模型数组吗?请记住,在 swift 中,数组是一种值类型。这意味着如果您将数组传递给另一个视图,您传递的是该数组的副本,而不是集合视图控制器中的数组。将模型数组包装在一个可以传递引用的对象中可能是一个更好的主意。更多关于 here.

此外,最好将重新加载与模型中的更改相关联,而不是与视图生命周期相关联。要使用您当前的代码做到这一点,您可以这样做:

var list = ["January","February","March","April","May","June", "July","August","September","October","November", "December"] {
   didSet {
      self.collectionView?.reloadData()
      // or
      self.soundBoard.reloadData()
      // I'm confused about which collection view you're using/trying to reload. 
   }
}

如果您有任何问题,请告诉我。我会留意并在需要时编辑我的答案。

这是另一个 ViewController 的代码,您可以在其中重新排序行并点击 <返回。

import UIKit

class soundboardTableViewController: UITableViewController {

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



    override func viewDidLoad() {
        super.viewDidLoad()


        self.navigationItem.rightBarButtonItem = self.editButtonItem

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

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


    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return list.count
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

        cell.textLabel?.text = list[indexPath.row]

        return cell
    }


    // Override to support conditional editing of the table view.
    override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the specified item to be editable.
        return true
    }


    /* Override to support editing the table view.*/
    override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
        if editingStyle == .delete {
            list.remove(at: indexPath.row)

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

            tableView.reloadData()
        }
    }

    // Override to support rearranging the table view.
    override func tableView(_ tableView: UITableView, moveRowAt indexPath: IndexPath, to: IndexPath) {
        /*let itemToMove = list[indexPath.row]
        list.remove(at: indexPath.row)
        list.insert(itemToMove, at: indexPath.row)

        UserDefaults.standard.set(self.list, forKey:"soundboard")
        UserDefaults.standard.synchronize()*/

        let itemToMove = list[indexPath.row]
        list.remove(at: indexPath.row)
        list.insert(itemToMove, at: to.row)

        UserDefaults.standard.set(self.list, forKey:"soundboard")
    }

    override func setEditing(_ editing: Bool, animated: Bool) {
        super.setEditing(editing, animated: animated)

        if(self.isEditing) {

        }
    }


    // Override to support conditional rearranging of the table view.
    override func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {
        // Return false if you do not want the item to be re-orderable.
        return true
    }



    // MARK: - Navigation

    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }


}

这里发生了两件事。首先,您似乎在 CollectionViewController 中有两个不同的集合视图; collectionView 继承自超类,soundboard 是您声明的。在 viewWillAppear 中,您告诉 collectionView 重新加载。如果这不是在 IB 中连接的那个,则什么都不会起作用。

第二个问题是,在 soundboardTableViewController 中,您使用正确的数据更新用户默认值,但在 CollectionViewController 中加载视图后,您从未阅读过它。

你应该移动这个:

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

在调用重新加载集合视图之前进入 viewWillAppear,然后确认您告诉正确的集合视图重新加载。