Search code examples
iosswiftxcode6subviewuitextfielddelegate

Next/Done button using Swift with textFieldShouldReturn


I have a MainView that adds a subview (signUpWindow) when a sign up button is pressed.

In my signUpWindow subview (SignUpWindowView.swift), I set up each field with a function, as an example:

func confirmPasswordText()
    {
        confirmPasswordTextField.frame=CGRectMake(50, 210, 410, 50)
        confirmPasswordTextField.placeholder=("Confirm Password")
        confirmPasswordTextField.textColor=textFieldFontColor
        confirmPasswordTextField.secureTextEntry=true
        confirmPasswordTextField.returnKeyType = .Next
        confirmPasswordTextField.clearButtonMode = .WhileEditing
        confirmPasswordTextField.tag=5
        self.addSubview(confirmPasswordTextField)
    }

I have the keyboard moving the signUpWindow up and down when it appears and disappears in the MainView.

SignUpWindowView implements the UITextFieldDelegate

My problem is that I am trying to configure the Next/Done button on the keyboard and am not sure which view (MainView or SignUpWindowView) to add the textFieldShouldReturn function. I have tried both, but can't even get a println to fire to test to see if the function is even being executed. Once I get the textFieldShouldReturn to fire, I am confident I can execute the necessary code to get the Next/Done buttons to do what I want, and will post the final solution to include the Next/Done function.

UPDATED to include an abbreviated version of SignUpWindowView.swift

import UIKit

class SignUpWindowView: UIView,UITextFieldDelegate {

let firstNameTextField:UITextField=UITextField()
let lastNameTextField:UITextField=UITextField()

override func drawRect(rect: CGRect){
    func firstNameText(){
        firstNameTextField.delegate=self
        firstNameTextField.frame=CGRectMake(50, 25, 200, 50)
        firstNameTextField.placeholder="First Name"
        firstNameTextField.returnKeyType = .Next
        self.addSubview(firstNameTextField)
     }

    func lastNameText(){
        lastNameTextField.delegate=self
        lastNameTextField.frame=CGRectMake(260, 25, 200, 50)
        lastNameTextField.placeholder="Last Name"
        lastNameTextField.returnKeyType = .Done
        self.addSubview(lastNameTextField)
     }

    func textFieldShouldReturn(textField: UITextField!) -> Bool{
        println("next button should work")
        if (textField === firstNameTextField)
        {
            firstNameTextField.resignFirstResponder()
            lastNameTextField.becomeFirstResponder()
        }
        return true
     }

    firstNameText()
    lastNameText()
}

Solution

  • I was attempting to test my textfields in the SignUpWindowView.swift, which is where all of the textFields are created. But, since I place SignUpWindowView into my MainViewController as a subview, all of my UITextField "handling" needed to be done in the MainView and NOT its subview.

    So here is my entire code (at the moment) for my MainViewController, which handles moving my SignUpWindowView up/down when the keyboard is shown/hidden and then moves from one field to the next. When the user is in the last text field (whose keyboard Next button is now set to Done in the subview) the keyboard tucks away and the user can then submit the form with a signup button.

    MainViewController:

    import UIKit
    
    @objc protocol ViewControllerDelegate
    {
        func keyboardWillShowWithSize(size:CGSize, andDuration duration:NSTimeInterval)
        func keyboardWillHideWithSize(size:CGSize,andDuration duration:NSTimeInterval)
    }
    
    class ViewController: UIViewController,UITextFieldDelegate
    {
        var keyboardDelegate:ViewControllerDelegate?
    
        let signUpWindow=SignUpWindowView()
        let signUpWindowPosition:CGPoint=CGPointMake(505, 285)
    
        override func viewDidLoad()
        {
            super.viewDidLoad()
    
            // Keyboard Notifications
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillShow:", name: UIKeyboardWillShowNotification, object: nil)
            NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillHide:", name: UIKeyboardWillHideNotification, object: nil)
    
            // set the textFieldDelegates
            signUpWindow.firstNameTextField.delegate=self
            signUpWindow.lastNameTextField.delegate=self
            signUpWindow.userNameTextField.delegate=self
            signUpWindow.passwordTextField.delegate=self
            signUpWindow.confirmPasswordTextField.delegate=self
            signUpWindow.emailTextField.delegate=self
        }
    
    
        func keyboardWillShow(notification: NSNotification)
        {
            var info:NSDictionary = notification.userInfo!
            let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as! NSValue
            let keyboardSize = keyboardFrame.CGRectValue().size
    
            var keyboardHeight:CGFloat = keyboardSize.height
    
            let animationDurationValue = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
    
            var animationDuration : NSTimeInterval = animationDurationValue.doubleValue
    
            self.keyboardDelegate?.keyboardWillShowWithSize(keyboardSize, andDuration: animationDuration)
    
            // push up the signUpWindow
            UIView.animateWithDuration(animationDuration, delay: 0.25, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
                self.signUpWindow.frame = CGRectMake(self.signUpWindowPosition.x, (self.signUpWindowPosition.y - keyboardHeight+140), self.signUpWindow.bounds.width, self.signUpWindow.bounds.height)
                }, completion: nil)
        }
    
        func keyboardWillHide(notification: NSNotification)
        {
            var info:NSDictionary = notification.userInfo!
    
            let keyboardFrame = info[UIKeyboardFrameEndUserInfoKey] as! NSValue
            let keyboardSize = keyboardFrame.CGRectValue().size
    
            var keyboardHeight:CGFloat = keyboardSize.height
    
            let animationDurationValue = info[UIKeyboardAnimationDurationUserInfoKey] as! NSNumber
    
            var animationDuration : NSTimeInterval = animationDurationValue.doubleValue
    
            self.keyboardDelegate?.keyboardWillHideWithSize(keyboardSize, andDuration: animationDuration)
    
            // pull signUpWindow back to its original position
            UIView.animateWithDuration(animationDuration, delay: 0.25, options: UIViewAnimationOptions.CurveEaseInOut, animations: {
                self.signUpWindow.frame = CGRectMake(self.signUpWindowPosition.x, self.signUpWindowPosition.y, self.signUpWindow.bounds.width, self.signUpWindow.bounds.height)
                }, completion: nil)
        }
    
        func textFieldShouldReturn(textField: UITextField) -> Bool
        {
            switch textField
            {
            case signUpWindow.firstNameTextField:
                signUpWindow.lastNameTextField.becomeFirstResponder()
                break
            case signUpWindow.lastNameTextField:
                signUpWindow.userNameTextField.becomeFirstResponder()
                break
            case signUpWindow.userNameTextField:
                signUpWindow.passwordTextField.becomeFirstResponder()
                break
            case signUpWindow.passwordTextField:
                signUpWindow.confirmPasswordTextField.becomeFirstResponder()
                break
            case signUpWindow.confirmPasswordTextField:
                signUpWindow.emailTextField.becomeFirstResponder()
                break
            default:
                textField.resignFirstResponder()
            }
            return true
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
        override func viewWillDisappear(animated: Bool) {
            NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillShowNotification, object: nil)
            NSNotificationCenter.defaultCenter().removeObserver(self, name: UIKeyboardWillHideNotification, object: nil)
        }
    
        @IBAction func signup()
        {
            signUpWindow.frame=CGRectMake(signUpWindowPosition.x, signUpWindowPosition.y, 485,450)
            signUpWindow.backgroundColor=UIColor.clearColor()
    
            self.view.addSubview(signUpWindow)
        }
    }