1

I would like to cancel an unwind segue if the textbox values are equal to nil. below is the current code. I used storyboard to connect the save button (saves values of text into database). I was thinking about using poptorootviewcontroller to ensure the textbook has values before performing segue. is their any way to do this with current code?

code inside of mainView to unwind back to-

@IBAction func unwind(_ segue: UIStoryboardSegue){
    print("Back in TableView")

}

button on childView perform unwind segue-

 @IBAction func saveAddress(_ sender: UIButton) {
    // save values to dictionary save dictionary to firebase under user, uid, addresses
    // uialert controller if fields are not completed do not allow segue if fields are not complete
    // perform segue to addresstableview

    let addy1: String = address1Txt.text!
    let addy2: String = address2Txt.text!
    let aptNum: String = aptTxt.text!
    let city: String = cityTxt.text!
    let state: String = stateTxt.text!
    let zip: String = zipTxt.text!

    // add UIAlert controller for address field == nothing
    if addy1.isEmpty && aptNum.isEmpty && city.isEmpty && state.isEmpty && zip.isEmpty
    {
        //add UIAlert Controller DO NOT PERFORM SEGUE IF TRUE
    }

    Address.sharedInsance.typedNewAddress = addy1 + "," + addy2 + "," + aptNum + "," + city + "," + state + "," + zip

    print("address save print",addy1, addy2, aptNum, city, state, zip)
    let key = ref.child("address").childByAutoId().key
    let setter = false
    let addyDict = ["address line 1":addy1,"address line 2":addy2,"apt Number":aptNum,"city":city,"state":state,"zip":zip,"keyID": key, "setter": setter] as [String : Any]
    let userID = Auth.auth().currentUser?.uid
    let childUpdates = ["/address/\(key)": addyDict]
    ref.child("users").child(userID!).updateChildValues(childUpdates)

}
  • 1
    you should create a segue from the entire original view controller instead of just the button going to the destination view controller. then you can trigger the segue anytime you want to use it instead of canceling an already triggered segue . – Nevin Jethmalani Mar 09 '18 at 21:52

2 Answers2

5

Given that I don't see you performing the segue in your @IBAction, we'll have to presume that you hooked your button up to both an @IBAction and an unwind segue. You should remove the segue from the button's "Connections Inspector" on the last tab on the panel on the right and instead, create an unwind segue from the view controller, itself, to the exit outlet:

create unwind segue

You can then select that segue in the panel on the left, click on the "attributes inspector" for that segue, give it a storyboard identifier:

enter image description here

Then you can programmatically perform the segue, using that storyboard identifier, only if appropriate in your remaining @IBAction, e.g.

@IBAction func didTapDoneButton(_ sender: Any) {
    // if the fields are `nil` or have a length of zero characters, show warning
    // and just `return` without ever performing unwind segue

    guard let firstName = textFieldFirstName.text?.trimmingCharacters(in: .whitespacesAndNewlines),
        let lastName = textFieldLastName.text?.trimmingCharacters(in: .whitespacesAndNewlines),
        firstName.count > 0, lastName.count > 0 else {
            let alert = UIAlertController(title: nil, message: "Please fill in all fields", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .default))
            present(alert, animated: true)
            return
    }

    // do something with firstName and lastName

    save(firstName: firstName, lastName: lastName)

    // now perform unwind segue

    performSegue(withIdentifier: "unwindHome", sender: sender)
}

Having shown you that, I believe the more robust approach is to not let the user tap the "done"/"save" button until the required fields are entered. Bottom line, rather than handling the error situation, design a UI where it is impossible to make such an error.

So, some of the key aspects of that would include:

  • Dim/disable the "done"/"save" button;
  • Set the "placeholder text" for the text fields to indicate that the field is required. E.g. a placeholder of "First name (required)" so that the user knows it's required.
  • Add editingChanged method for the various text fields that enables/disables the "done" button as appropriate:

    @IBAction func editingChanged(_ sender: UITextField) {
        if let firstName = textFieldFirstName.text?.trimmingCharacters(in: .whitespacesAndNewlines),
            let lastName = textFieldLastName.text?.trimmingCharacters(in: .whitespacesAndNewlines),
            firstName.count > 0, lastName.count > 0 {
            doneButton.isEnabled = true
        } else {
            doneButton.isEnabled = false
        }
    }
    

    Obviously hook this up to the "editingChanged" action for all of the relevant text fields.

This yields a "Done" button (the one in the upper right corner of this demo) that is disabled until there is at least some text in all of the text fields:

enter image description here

Bottom line, rather handling the error, prevent it in the first place.

Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • I did most of what you are explaining except the part of naming the segue identifier therefore I did not have the option to use the line performSegue(withIdentifier: "unwindHome", sender: sender) thanks! will implement and if I have trouble I will come back and ask for your assistance. – Omar Al-Eisa Mar 09 '18 at 23:03
  • FWIW, I added an alternative approach that I think is better, i.e. rather than handling error, prevent it from ever happening at all. – Rob Mar 09 '18 at 23:09
  • I like it :) whats your email address? – Omar Al-Eisa Mar 10 '18 at 02:23
  • I'd rather not post my email address on a public forum, but if you go to my S.O. profile, there's a link to my web site, that has a "email" link on it, where you can send me a private note. – Rob Mar 10 '18 at 02:45
0

You should override shouldPerformSegue method and return false if the textbook fields are empty.

override func shouldPerformSegue(withIdentifier identifier: String, sender: Any?) -> Bool {

}
bseh
  • 447
  • 7
  • 13