Reputation: 387
I m confuse about call back using protocol and delegate.
The problem is. I have two viewcontrollers vcA & vcB
and vcA
have a tableView, vcB
have a button.
vcA click the cell to vcB
.
Then I want to click the button in vcB
and do the following two things.
1.vcA tableView reloadData.
2.vcB popViewcontroller To vcA.
I can't understand how to solve this issue.
Have any sample to teach me?
Thanks.
Upvotes: 0
Views: 79
Reputation: 1915
There are multiple ways to do this.
1: Put tableView.reloadData()
in viewDidAppear()
and then just pop vcB
2: When you are pushing vcB you create a reference to it and then in vcB you have a listener that you apply to the reference. like so:
class viewControllerB: UIViewController {
var reloadTableView: (() -> ())
@objc func buttonPressed() {
reloadTableView()
self.navigationController?.popViewController(animated: true)
}
}
And then:
let vcB = viewControllerB()
vcB.reloadTableView = {
self.tableView.reloadData()
}
present(vcB, animated: true)
3: Do as Sh_Khan
Upvotes: 0
Reputation: 96
Your vcA
has a reference to the vcB
, so you are able to write something like this in the vcA
class vcA {
var vcB: vcB?
...
vcB?.doSmth()
....
}
but there is no way for you to call vcA
from the vcB
since it doesn't have a reference to it. So to let vcA
know that something happened in vcB
or to call some function from vcB
you can do several things.
Delegates, Key-Value Observing, Reactive Programming and some others.
Since you asked for the delegates solution lets stick to it.
The general idea behind delegates is as the name says to delegate
someone else to do something. In your case, you want to delegate button click handling to the vcA
. To do so, you will need a couple of things.
Next steps are just the implementation of the idea described above.
class VcA {
var vcB: VcB?
...
vcB?.delegate = self
...
vcB?.doSmth()
....
}
extension VcA: VcBDelegate {
func buttonIsClicked() {
// reload data
// pop vcB
}
}
protocol VcBDelegate: class {
func buttonIsClicked()
}
class VcB {
var delegate: VcBDelegate?
...
// when the button is clicked
// delegate handling to someone who is 'listening' for this event
self.delegate?.buttonIsClicked()
...
}
Notice how delegate
in VcB is optional, meaning that if no one is signed as a delegate for VcB, the event will simply be ignored.
Upvotes: 0
Reputation: 432
It's not possible to call the methods of any VC objects if it's not in your memory.
For the first time, it vcB will not be in memory. Hence the object of the same is not in existence.
If you really want to call a function of that class and if its feasible crate an object of vcB and call the method. or you might try a shared object of the VC and keep on using the same if it's feasible. you may post exact scenario so that people can suggest something better
Upvotes: 0
Reputation: 100533
This is the delegate solution , but it's better to put the self.tableView.reloadData()
method inside viewDidAppear
, as it's being called when you pop VcB
class VcA: UIViewController ,TableRefresh {
func reloadTable()
{
// reload here
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let des = segue.destination as! VcB
des.delegate = self
}
}
protocol TableRefresh {
func reloadTable()
}
class VcB: UIViewController {
var delegate: TableRefresh?
@IBAction func closeClicked(_ sender: UIButton) {
self.delegate?.reloadTable()
// pop here
}
}
Upvotes: 1
Reputation: 4451
I hope this could work for you:
class vcA : UIViewController {
override func viewWillAppear(_ animated: Bool) {
tableView.reloadData()
}
}
class vcB : UIViewController {
@IBAction fun button(bin : UIButton){
self.navigationController.popViewController(true)
}
}
Upvotes: 0