Alec O'Connor
Alec O'Connor

Reputation: 265

How to send values to a parent view controller in Swift

I am working on a settings view controller screen for my iOS app written in swift. I am using a navigation controller to run the main settings table view which shows the cell titled, "Input Method." The current method is listed on the right of the cell. They can click the cell to go to the next view controller where they can select the input method that they'd like.

From here, there are two sections. The first is the input method to choose (touchscreen or joystick). The second section is joystick specific on whether or not the person is a lefty or righty. I don't want to have the vc unwind when they choose one box because they may choose one in another section too.

My question: How can I update the text field in the parent controller from the child controller.

Problems I'm having for optional solutions:

let parentVC: UIViewController = (self.navigationController?.parentViewController)!
parentVC.inputMethod.text? = cellSelected // This doesn't work because it cannot find the label inputMethod.

viewDidLoad() will cause a lag and the user sees the old method before it changes.

I cannot find out how to run a segue when someone clicks the back button at the upper left hand side in the navigation controller, since the navigation controller controls the segue.

Upvotes: 15

Views: 21776

Answers (3)

javiazo
javiazo

Reputation: 1982

It is not a good idea to cast the parent view controller, even when you are sure which class represents. I'll do it with a protocol:

In the child controller add a protocol like:

protocol ChildNameDelegate {
    func dataChanged(str: String)
}

class ChildClass {

    weak var delegate: ChildNameDelegate?

    func whereTheChangesAreMade(data: String) {
        delegate?.dataChanged(data)
    }
}

And in the parent:

class ParentClass: ChildNameDelegate {

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        guard let segueId = segue.identifier else { return }

        switch segueId {
        case "childSegue":
            let destVC = segue.destinationViewController as! ChildClass
            destVC.delegate = self
            break
        default:
            break
        }
    }

    // Child Delegate
    func dataChanged(str: String) {
        // Do whatever you need with the data
    }
}

Upvotes: 51

Alec O'Connor
Alec O'Connor

Reputation: 265

I found a solution here: Modifing one variable from another view controller swift http://www.raywenderlich.com/115300/swift-2-tutorial-part-3-tuples-protocols-delegates-and-table-views

Instead of trying to access the view controller directly (which would be easier if it weren't returning a nil for the view controller) you can use a delegate method to adjust the variables. The delegate worked like a charm!

Upvotes: 0

thislooksfun
thislooksfun

Reputation: 1089

You need to cast the parentViewController to whatever custom class it has. For example, if the parent has the class ExampleParentController, you would write:

let parentVC = (self.navigationController?.parentViewController)! as! ExampleParentController
parentVC.inputMethod.text? = cellSelected

Upvotes: 1

Related Questions