首页 > 解决方案 > 使用分段控制刷新子控制器

问题描述

我的父视图控制器包含两个容器视图和一个在两个视图之间切换的分段控件。每个 Container View 显示一个 tableView。这两个子视图控制器称为printingView 和completedView。

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

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

父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 PrintingVC(CompletedVC 具有相同的布局)

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

标签: iosswiftuitableviewuicontainerview

解决方案


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


使用您当前的方法,对于您的每个子 VC,您正在将数据从 Core Data 加载viewDidLoad()到一个数组中。然后,您使用该数组来填充表。

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

问题是,这不会更新CompletedVC.

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

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


更好的方法是使用 Fetched Results Controller 和 Managed Object Context 来观察Core Data 的变化并自动更新/刷新表视图。

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


推荐阅读