I have a UIViewController
. It has a container view and a UITableViewController
is embedded within that.
The table view displays an array of 20 numbers. Tapping on the Delete button shows an action sheet which gives 2 options to modify the above array.
I have two functions inside UITableViewController
to modify the array.
class TableViewController: UITableViewController {
fileprivate var values = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
override func viewDidLoad() {
super.viewDidLoad()
}
func deleteFirstTen() {
values.removeSubrange(values.startIndex..<values.startIndex.advanced(by: 10))
tableView.reloadData()
}
func deleteLastTen() {
values.removeSubrange(values.startIndex.advanced(by: 10)..<values.endIndex)
tableView.reloadData()
}
// MARK: - Table view data source
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return values.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
cell.textLabel?.text = "\(values[indexPath.row])"
return cell
}
}
I initiatialize the view controller and call those functions from the UIViewController
but it's not doing anything.
class ViewController: UIViewController {
@IBAction func didTapDeleteButton(_ sender: UIBarButtonItem) {
let tableViewController = storyboard?.instantiateViewController(withIdentifier: "TableViewController") as! TableViewController
let sheet = UIAlertController(title: nil, message: "Do You Want to Delete...", preferredStyle: .actionSheet)
sheet.addAction(UIAlertAction(title: "1 - 10", style: .default) { action in
tableViewController.deleteFirstTen()
})
sheet.addAction(UIAlertAction(title: "11 - 20", style: .default) { action in
tableViewController.deleteLastTen()
})
sheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(sheet, animated: true, completion: nil)
}
}
How can I call a function in an embedded view controller properly?
Demo project uploaded here.
Based on your sample project, this is a solution:
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
var tableViewController: TableViewController? = nil
// this method is a point in which you can hook onto segues
// coming from this viewController and do anything you want to
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// if it's a segue going to TableViewController and it has
// the identifier we set in the storyboard, then this is the
// tableViewController we want to get
if segue.identifier == "embedSegue",
let vc = segue.destination as? TableViewController {
self.tableViewController = vc
}
}
@IBAction func didTapDeleteButton(_ sender: UIBarButtonItem) {
let sheet = UIAlertController(title: nil, message: "Do You Want to Delete...", preferredStyle: .actionSheet)
sheet.addAction(UIAlertAction(title: "1 - 10", style: .default) { action in
self.tableViewController?.deleteFirstTen()
})
sheet.addAction(UIAlertAction(title: "11 - 20", style: .default) { action in
self.tableViewController?.deleteLastTen()
})
sheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
present(sheet, animated: true, completion: nil)
}
}
You want to get the tableViewController
from the segue created for you in storyboards. prepareForSegue:sender:
method is a point in which you can hook onto a segue coming from the given viewController to another one (even when it is embedding segue). Check the above code for working solution.
Do not forget to set an identifier for the segue (in my case I used "embedSegue"
, but use whatever makes sense for you). In your case it is not necessary - you can simply test if the segue goes to TableViewController
instance, but it is a good practice to use segue identifiers - it pays off when the project gets bigger. You can set it in storyboard by clicking on the segue (the arrow from ViewController
to the TableViewController
) and on the right panel in the Attributes Inspector there is a field for the identifier.