El Tomato El Tomato - 12 days ago 5
Swift Question

Making a Delegate Call from One View Controller to Another

One of the things that I haven't done in Swift is use of a delegate. So I'm trying to make a delegate call from one view controller to another to pass data.

I have two view controllers across two separate storyboards. One is HomeViewController, the 1st view controller. That's where the user is at right now. Then he taps the right navigation item button to go to SettingsViewController, the 2nd view controller. He then taps a navigation item button to go back to the 1st view controller. On the way back, SettingsViewController sends an

Int
value to HomeViewController. And what I have is the following.

// 1st view controller //
class HomeViewController: UIViewController, SettingsViewControllerDelegate {
@IBAction func rightTapped(sender: AnyObject) {
let storyboard = UIStoryboard(name: "Settings", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("InitialController") as! UINavigationController
let view = controller.topViewController as! SettingsViewController
view.selectedRow = lineSelection
self.navigationController?.pushViewController(view, animated: true)
}

override func viewDidLoad() {
let storyboard = UIStoryboard(name: "Settings", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("InitialController") as! UINavigationController
let settingsViewController = controller.topViewController as! SettingsViewController
settingsViewController.delegate = self
}

func didChangeLine(number: Int) {
print(number) // <<<<<<<<< not getting a delegate call
}
}

// 2nd view controller //
protocol SettingsViewControllerDelegate {
func didChangeLine(number: Int)
}

class SettingsViewController: UIViewController {
var selectedRow = Int() // the row selected from a table view
var rightButton = UIBarButtonItem()

override func viewDidLoad() {
rightButton = UIBarButtonItem(title: "Change", style: .Plain, target: self, action: #selector(changeNumber))
self.navigationItem.rightBarButtonItem = rightButton
}

// going back to 1st view controller (HomeViewController)
func changeNumber() {
self.delegate?.didChangeLine(selectedRow)
self.navigationController?.popViewControllerAnimated(true)
}
}


I'm not getting a call when the user goes back from the 2nd (Settings) to the 1st view controller (Home). I can pass data in a different approach, but I want to what I'm doing wrong with this case.

Thanks.

Answer

You need to override prepareForSegue in 1st viewcontroller for passing 1st viewcontroller ref to secondviewcontroller delegate property.

override func prepareForSegue(segue: UIStoryboardSegue?, sender: AnyObject?) {
        let viewController = segue.destinationViewController as! SettingsViewController
        viewController.delegate = self
}

In HomeViewController viewDidLoad code doesn't make any sense because you're performing segue from storyboard.

UPDATED

@IBAction func rightTapped(sender: AnyObject) {
    let storyboard = UIStoryboard(name: "Settings", bundle: nil)
    let controller = storyboard.instantiateViewControllerWithIdentifier("InitialController") as! UINavigationController
    let view = controller.topViewController as! SettingsViewController
    view.delegate = self

   view.selectedRow = lineSelection
    self.navigationController?.pushViewController(view, animated: true)
}

and you can directly get the SettingViewController ref. just set viewcontroller storyboard id and get it like this

 let storyboard = UIStoryboard(name: "Settings", bundle: nil)
 let controller = storyboard.instantiateViewControllerWithIdentifier("InitialController") as! UINavigationController

let controller = storyboard.instantiateViewController(withIdentifier: "SettingsViewController") as! SettingsViewController