-2

How can I call func checkField when nextButton is tapped? If no field is empty in ManagedTableEleventhViewController, I'd like to segue to TwelvethViewController.

I have a UIViewController ElevethViewController which holds a container view. The container view has an embed segue to a UITableViewController ManagedTableEleventhViewController. From ElevethViewController there is a Show segue to a UIViewController TwelevethViewController

The View hierarchy looks like this:

ElevethViewController 
  Container View
     ManagedTableEleventhViewController embedded in Container View with Embed segue
      Show segue "eleventhToTwelveth" to "Tweleveth View Controller"
       Embed segue "myEmbeddedSegue" to "Managed Table"

ManagedTableEleventhViewController contains 4 static cells containing 1 textField each and one empty static cell.

 import UIKit
 import Foundation

  protocol DelegateEleventh {
    func checkField(sender:EleventhViewController)
   }

 class EleventhViewController: UIViewController {

      var delegate:DelegateEleventh?
      @IBAction func nextButton(_ sender: Any) {

         //if delegate is not nil, call func checkField
           if let delegateVC = delegate {
        delegateVC.checkField(sender:self) 

    } else{
        print("delegateVC value \(delegate)") //prints nil
     }
   }       
 } //end of class




 import Foundation
 import UIKit

 class ManagedTableEleventhViewController:    
 UITableViewController,UITextFieldDelegate,DelegateEleventh {


@IBOutlet weak var fullName: UITextField!
@IBOutlet weak var flatNumber: UITextField!
@IBOutlet weak var streetAddress: UITextField!
@IBOutlet weak var phoneNumber: UITextField!


override func viewDidLoad() {
    super.viewDidLoad()
}


//When nextButton is touched in EleventhViewController, call this method
func checkField(sender:EleventhViewController){

    for cell in self.tableView.visibleCells {
        for sub in cell.contentView.subviews{

            if sub is UITextField{

let textF = sub as? UITextField
         //if textField is empty, make its border red,else clear
                if textF?.text == "" {
                    self.hasText = false
                    textF?.layer.cornerRadius = 8.0
                    textF?.layer.masksToBounds = true
                    textF?.layer.borderColor = UIColor.red.cgColor
                    textF?.layer.borderWidth = 1.0
                      } else {
                    self.hasText = true

                    //segue to nextViewcontroller
               sender.performSegue(withIdentifier: "elevethToTwelveth", sender: sender)

                }
            }// end of if sub is UITextField

        }//end of for sub in cell.contentView

    } //end of  for cell in tableView
}



       //KEYBOARD DOES NOT RESIGN....
// When tapping outside of the keyboard, close the keyboard down
 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
 }

 // used to check textField has a string value
 var hasText:Bool! 


  //called by ManagedTableEleventhViewController (namely the delegate) when    
           editing has begun
func textFieldDidBeginEditing(_ textField: UITextField) {

    if textField.text == "" {

        print("false value in textFieldDidBeginEditing")
        self.hasText = false
        textField.layer.cornerRadius = 8.0
        textField.layer.masksToBounds = true
        textField.layer.borderColor = UIColor.red.cgColor
        textField.layer.borderWidth = 1.0

    } else {
        print("true value in textFieldDidBeginEditing")
        textField.layer.borderWidth = 1
        textField.layer.borderColor = UIColor.white.cgColor
        print("call in else")
        self.hasText = true
    }
 }


//called by ManagedTableEleventhViewController (namely the delegate) when    
             // editing stopped
   func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {

         //if textField is empty make the border red
    if textField.text == "" {
        self.hasText = false
        textField.layer.cornerRadius = 8.0
        textField.layer.masksToBounds = true
        textField.layer.borderColor = UIColor.red.cgColor
        textField.layer.borderWidth = 1.0
        print("false value in textFieldDidEndEditing")
             } else {
        textField.layer.borderWidth = 1
        textField.layer.borderColor = UIColor.white.cgColor
        print("true value in textFieldDidEndEditing")
        self.hasText = true
    }
}

    // Stop Editing on Return Key Tap. 
     func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    return true
  }
}//end of class

Main.storyboard scene

bibscy
  • 2,598
  • 4
  • 34
  • 82
  • 1
    Looks like `IBOutlet` `fullName` and the other ones are not connected in Interface Builder (as stated in the debug variable listing). Btw: Why are you using `var` for constants? Doesn't you get a bunch of warnings? – vadian Mar 04 '17 at 19:52
  • @vadian I have made the keys for UserDefaults constants now. If you look in the first screenshot in the Connections inspector you will see that fullName is connected in Interface Builder. – bibscy Mar 04 '17 at 19:56
  • 2
    It is not, because the instance created with the default initializer `ManagedTableEleventhViewController()` is **not** the instance in Interface Builder. You need the actual reference to the controller from the segue. – vadian Mar 04 '17 at 19:59
  • PS : Not related, but you don't need to add actions for delegate methods declared by the framework. Just implement the methods you need. – vadian Mar 04 '17 at 20:04
  • In your func nextButton method, the following line -- let managedTable = ManagedTableEleventhViewController() -- creates a new instance of ManagedTableEleventhViewController. You don't want to do this. You want to reference the one created via the mainStoryBoard. You need to reference it through the segue from EleventhViewController to ManagedTableEleventhViewController. – Magnas Mar 04 '17 at 20:24
  • @Magnas How can I get a reference to ManangedTableEleventhViewController? I tried `if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ManagedTableID") as? UITableViewController { vc.checkField(fromViewController: self) }`,but I get value of type UITableViewController has no member checkField. – bibscy Mar 04 '17 at 21:54
  • Try -- if let vc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ManagedTableID") as? ManagedTableEleventhViewController { vc.checkField(fromViewController: self) } But really I would probably implement prepareForSegue and get a ref to the tableViewController through there using whatever identifier you have assigned to the embed segue. – Magnas Mar 05 '17 at 05:18
  • Don't instantiate the controller explicitly. Since you are using segues, the expected reference is the destination controller of the segue. – vadian Mar 05 '17 at 07:56
  • @vadian I don't want to segue to ManagedTableEleventhViewController. I want to segue to TwelvethViewController. I have updated my question too. – bibscy Mar 08 '17 at 22:13
  • @matt could you please tell me if I have solved my problem in the right way. I haven't managed to resolve it using delegates and protocols. Many thanks for all your help – bibscy Mar 09 '17 at 12:14

1 Answers1

1

Thanks to this answer I have obtained the desired result.

class EleventhViewController: UIViewController {

@IBAction func nextButton(_ sender: Any) {
 var managed: ManagedTable? {
    return self.childViewControllers.last as! ManagedTable?
   //if there is no empty field after checkField(sender:_) is called,    
    // segue to TwelvethViewController
   managed?.checkField(sender: self)
    } 
  }
}



 class ManagedTableEleventhViewController {

 // holds a true value if textField contains a value
  var hasText:Bool!

 //holds a true/false value for each textField after iterating through them    
      //with a for loop
var textValues = [Bool]()

//When nextButton is touched in EleventhViewController, call this method
func checkField(sender:EleventhViewController) {


    for cell in self.tableView.visibleCells{
        for sub in cell.contentView.subviews{

            if sub is UITextField{

let textF = sub as? UITextField
         //if textField is empty, make its border red,else clear
                if textF?.text == "" {
                    self.hasText = false
                    self.textValues.append(self.hasText)
                    textF?.layer.cornerRadius = 8.0
                    textF?.layer.masksToBounds = true
                    textF?.layer.borderColor = UIColor.red.cgColor
                    textF?.layer.borderWidth = 1.0
                } else {
                    self.hasText = true
                    self.textValues.append(self.hasText)

                }
            }// end of if sub is UITextField

        }//end of for sub in cell.contentView

    } //end of  for cell in tableView

   //if no field is empty perform segue to TwelvethViewController, 
       //otherwise reset textValues array
      if !self.textValues.contains(false){
         sender.performSegue(withIdentifier: "eleventhToTwelveth", sender: sender)
        }
     self.textValues.removeAll()
    } //end of checkField(sender:_)
}//end of class
Community
  • 1
  • 1
bibscy
  • 2,598
  • 4
  • 34
  • 82