使用分段控制刷新 Child 个控制器

Refreshing Child Controllers with Segmented Control

我有 parent 视图控制器,其中包含两个容器视图和一个在两个视图之间切换的分段控件。每个 Container View 显示一个 tableView。两个 child 视图控制器称为 printingView 和 completedView。

用户可以将一个项目标记为完成,并将其从 printingView tableView 中删除并显示在 completedView tableView 上。我遇到的问题是当 segmentedControl 切换到显示该视图时刷新 completedView tableView。到目前为止,当项目从 printingView 中移除时,我需要导航到另一个页面并返回到 PrintJobs ViewController 才能看到该项目出现在 completedView 中。

实施后,两个视图被适当地隐藏和显示。由于页面上的视图仍然处于活动状态,因此 child tableView 在分段控制器切换时不会更新。我如何实现 child 表格视图以便在调用 segmentedControl 时重新加载?

Parent VC

class PrintJobsVC: UIViewController {

    @IBOutlet weak var printingView: UIView!
    @IBOutlet weak var completedView: UIView!

    var printer:PrinterDisplay? // passed from the VC before via segue

    @IBAction func toggleSegmentedController(_ sender: UISegmentedControl) {
        switch sender.selectedSegmentIndex {
        case 0:
            // PrintingView
            setView(view: printingView, hidden: false)
            setView(view: completedView, hidden: true)

        case 1:
            // CompletedView
            setView(view: printingView, hidden: true)
            setView(view: completedView, hidden: false)

        default:
            print("hit default case of toggleSegmentedController")
            setView(view: printingView, hidden: false)
            setView(view: completedView, hidden: true)
        }
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "PrintingSegue", let nextVC = segue.destination as? IndividualPrintingVC {
            print("individualPrinting segue")
            nextVC.printer = printer
        } else if segue.identifier == "CompletedSegue", let nextVC = segue.destination as? IndividualCompletedVC {
            print("completedSegue")
            nextVC.printer = printer
        }
    }

    func setView(view: UIView, hidden: Bool) {
        UIView.transition(with: view, duration: 0.3, options: .transitionCrossDissolve, animations: {
            view.isHidden = hidden
        })
    }

}

Child打印VC(已完成VC排版相同)

class PrintingVC: UIViewController {
    @IBOutlet weak var tableView: UITableView!
    var printer:PrinterDisplay?
    var printingArray:[PrintingDisplay] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        getCoreData() // retrieves from core data and stores in printingArray
    }
    
    override func viewWillAppear(_ animated: Bool) {
        DispatchQueue.main.async { self.tableView.reloadData() }
    }
}

// tableview methods
extension PrintingVC: UITableViewDelegate, UITableViewDataSource {
    // set up how many rows are in the tableview
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return printingArray.count
    }
    
    // sets up a cell in the tableview
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "PrintingCell", for: indexPath as IndexPath) as! PrintingTableViewCell
        
        let item = printingArray[indexPath.row]
        // setup cell parameters

        return cell
    }
}

// mark the item as complete, remove from printingArray, modify Core Data
extension PrintingVC: PrintingTableViewCellDelegate {
    func markCompleted(row: Int, indexPath: IndexPath) {
        let item = printingArray[row]
        // confirm that the user wants to complete print
        let alert = UIAlertController(title: "Are you sure?", message: "\(item.item) will be marked as completed. It can be found in the printer's individual page", preferredStyle: .alert)
        alert.addAction(UIAlertAction(title: "OK", style: .default, handler: {action in
            self.markCompletedCoreData(uid: item.uid)
            self.printingArray.remove(at: row)
            self.tableView.deleteRows(at: [indexPath], with: .fade)
        }))
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        self.present(alert, animated: true)
    }
}

有多种方法可以做到这一点...


使用您当前的方法,对于您的每个子 VC,您正在将 viewDidLoad() 中的核心数据中的数据加载到一个数组中。然后使用该数组填充 tables.

当您在 PrintingVC 中将项目标记为“已完成”时,您更新核心数据,从数组中删除元素,并从 table 中删除行。

问题是,这不会更新 CompletedVC 中的数组。

因此,您需要让 PrintingVC 告诉 PrintJobsVC 记录已更改(使用闭包或协议/委托模式),然后 PrintJobsVC 会告诉 CompletedVC 更新 its 数组并重新加载其 table.

这种方法相当“蛮力”,但会奏效。


更好的方法可能是使用获取结果控制器和托管对象上下文来观察对核心数据的更改并自动更新/ 刷新 table 视图。

你需要做一些研究(那里有很多教程)来学习如何做到这一点。