-1

I'm trying to reload table view in Calculation controller, pressing back navigation button on Setup controller (red arrow on screenshot).

Which is the best way to do it? Thanks !

Mohmmad S
  • 5,001
  • 4
  • 18
  • 50

5 Answers5

5

In a navigation controller its's pretty easy. In Swift the most efficient way is a callback closure, it avoids the overhead of protocol/delegate.

  • In SetupController declare a callback property, a closure with no parameter and no return type

    var callback : (() -> Void)?
    

    and call it in viewWillDisappear. viewWillDisappear is allways called when the back button is pressed.

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        callback?()
    }
    
  • In CalculationController assign the callback in prepare(for

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        ...
        let setupController = segue.destination as! SetupController
        setupController.callback = { 
            self.tableView.reloadData()
        }
    
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thank's @vadian! I guess, in my case callback property will be in setup vc. And prepare(for: sender:) method will be in calculation vc. – butkovskiym Dec 20 '18 at 09:30
2

Using Delegate Pattern

Create delegate with some method for second ViewController. Implement this protocol to first ViewController and when this method is called, reload UITableView data (in overriden prepare(for:sender:) set delegate of second ViewController to self). When second ViewController will disappear, call method on delegate variable of second ViewController.

Now when you're able to use delegates, you can easily add parameter to delegate's method and pass data from second to first ViewController.


protocol SecondVCDelegate: class { // define delegate protocol
    func controllerDismissed()
}

class ViewController: UIViewController {
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "yourIdentifier" {
            let destinationVC = segue.destination as! SecondViewController
            destinationVC.delegate = self
        }
    }
}

extension ViewController: SecondVCDelegate {
    func controllerDismissed() { // this is called when you call delegate method from second VC
        tableView.reloadData()
    }
}

class SecondViewController: UIViewController {
    
    weak var delegate: SecondVCDelegate? // delegate variable
    
    override func viewWillDisappear(_ animated: Bool) {
        delegate?.controllerDismissed() // call delegate's method when this VC will disappear
    }
    
}
Community
  • 1
  • 1
Robert Dresler
  • 10,580
  • 2
  • 22
  • 40
1

An easy solution is to reload the tableView, when the view is going to appear again.

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
}

Alternative solutions could be to implement unwindSegue or delegation.

Grumme
  • 794
  • 2
  • 9
  • 31
  • 1
    I agree. But since he doesn't make any networking calls etc. - I'm sure he'll be fine with this solution :-) – Grumme Dec 20 '18 at 08:53
  • He does not mention anything about passing data between the View Controllers. – Grumme Dec 20 '18 at 09:19
1

to achieve this you have multiple solutions first of all you have to know what is the best to use by your case,

1- are you passing data back to the CalculationVC

2- do you just need to reload the CalculationVC each time it appears ?

for the first case you use what called Delegates in swift.

for the second case you can use a life-cycle function that is called viewWillAppear() in the ViewController.

for the Delegate case you can find tons of articles online this one recommended for newbies !

and for the second case just use this code.

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
}
Mohmmad S
  • 5,001
  • 4
  • 18
  • 50
0

Try this code

protocol VC2Delegate: class {
    func viewController(_ myVC2: VC2?, didFinishEditingWithChanges hasChanges: Bool)
}

class VC2 {
    private weak var: VC2Delegate? delegate?
    weak var: VC2Delegate? delegate?

    @IBAction func finishWithChanges() {
        delegate.viewController(self, didFinishEditingWithChanges: true)
    }

    @IBAction func finishWithoutChanges() {
        delegate.viewController(self, didFinishEditingWithChanges: false)
    }
}

//VC1: implement the VC2Delegate protocol
class VC1: VC2Delegate {
    var: Bool _needsReload?

    func awakeFromNib() {
        super.awakeFromNib()
        needsReload = true
    }

    func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        reloadTableIfNeeded()
    }
@IBAction func displayVC2() {
}