简体   繁体   中英

Swift – Table view data not reloading after dismissing view controller

I have a view in my app called JournalViewController that I'm presenting over my PastSessionsViewController . PastSessions has a table view that the user can tap to edit and bring up the journal.

When the user edits an entry and saves it (saving to CoreData), dismissing JournalViewController I'd like for the table view in PastSessions to reflect those changes and show the updated table cell.

I'm calling tableView.reloadData() in PastSessionsViewController viewDidLoad() but that doesn't seem to be working. I've also added a delegate for JournalViewController to interact with PastSessionsViewController ahead of dismissViewController

Here's some code to look at:

In PastSessionsViewController :

class PastSessionsViewController: UIViewController, UITableViewDelegate, JournalVCDelegate {
    weak var tableView: UITableView?
    weak var backButton: UIButton?

    let pastSessionsDataSource: PastSessionsDataSource

    init() {
        pastSessionsDataSource = PastSessionsDataSource()
        super.init(nibName: nil, bundle: nil)
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let tableView = UITableView()
        tableView.backgroundColor = nil
        tableView.delegate = self
        tableView.dataSource = pastSessionsDataSource
        tableView.registerClass(EntryCell.self, forCellReuseIdentifier: "cell")
        view.addSubview(tableView)
        self.tableView = tableView
    }

    override func viewDidAppear(animated: Bool) {
        tableView?.reloadData()
    }

    func didFinishJournalVC(controller: JournalViewController) {
        var newDataSource = PastSessionsDataSource()
        tableView?.dataSource = newDataSource
        // tried this ^, but it's causing the app to crash 

        // tableView?.reloadData() <- this isn't doing the trick either
        dismissViewControllerAnimated(true, completion: nil)
    }

    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let editJournalVC = JournalViewController(label: "Edit your thoughts")
        editJournalVC.delegate = self

        presentViewController(editJournalVC, animated: true, completion: nil)
    }
}

In JournalViewController :

protocol JournalVCDelegate {
    func didFinishJournalVC(controller: JournalViewController)
}

class JournalViewController: UIViewController, UITextViewDelegate {
    var delegate: JournalVCDelegate! = nil

    func doneJournalEntry(sender: UIButton) {
        journalEntryTextArea?.resignFirstResponder()

        ... do some core data saving ...
        delegate.didFinishJournalVC(self)
    }
}

In PastSessionsDataSource :

   import UIKit
   import CoreData

   class PastSessionsDataSource: NSObject {
        var arrayOfEntries = [Entry]()
        var coreDataReturn: [Meditation]?

        func prepareEntries() {
          // gets stuff from coredata and formats it appropriately
        }

        override init() {
            super.init()
            prepareEntries()
        }
    }

    extension PastSessionsDataSource: UITableViewDataSource {
        func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return arrayOfEntries.count
        }

        func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! EntryCell

            ... set up the labels in the cell ...

            return cell
        }
    }

Thanks for looking!

viewDidLoad is called when the view controller load its view at the first time, so basically it will only be called once during the view controller's whole life cycle.
One quick solution is to put tableView.reloadData() in PastSessionsViewController viewWillAppear() or viewDidAppear() .
However I do not like this quick solution as every time you dismiss JournalViewController , the table view will be reloaded, even the user has not changed anything on JournalViewController (for example, cancel the edit). So I suggest to use delegate approach between PastSessionsViewController and JournalViewController , when the user actually edit the data on JournalViewController then inform PastSessionsViewController to refresh the table.

You are currently prepare entries only on init of PastSessionsDataSource, but not after you did CoreData changes. So each time when you reloadData for tableView you work with the same data set loaded initially. As a quick hack you can try to updated viewDidAppear in a following way:

 override func viewDidAppear(animated: Bool) {
        if let tableView = tableView {
          let dataSource = tableView.dataSource! as PastSessionsDataSource
          dataSource.prepareEntries()
          tableView.reloadData()
        }
 }

Your tableView property is probably nil in viewDidAppear , based on your listed code. The reason is that in viewDidLoad you construct a UITableView as tableView , and that is a local variable. You need to assign that variable to the property:

self.tableView = tableView

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM