Кнопка «Далее/Готово» с использованием Swift с textFieldShouldReturn

У меня есть MainView, который добавляет подвид (signUpWindow) при нажатии кнопки регистрации.

В моем подпредставлении signUpWindow (SignUpWindowView.swift) я настроил каждое поле с помощью функции, например:

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)
    }

У меня есть клавиатура, перемещающая signUpWindow вверх и вниз, когда она появляется и исчезает в MainView.

SignUpWindowView реализует UITextFieldDelegate

Моя проблема в том, что я пытаюсь настроить кнопку «Далее/Готово» на клавиатуре и не уверен, в какое представление (MainView или SignUpWindowView) добавить функцию textFieldShouldReturn. Я пробовал оба, но не могу даже запустить println, чтобы проверить, выполняется ли функция. Как только я заставлю textFieldShouldReturn сработать, я уверен, что смогу выполнить необходимый код, чтобы заставить кнопки «Далее/Готово» делать то, что я хочу, и опубликую окончательное решение, включающее функцию «Далее/Готово».

ОБНОВЛЕНО, чтобы включить сокращенную версию 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()
}

person Amy Plant    schedule 28.04.2015    source источник
comment
что вы устанавливаете в качестве делегата текстовых полей?   -  person André Slotta    schedule 28.04.2015
comment
подтвердитьPasswordTextField.delegate=я   -  person Amy Plant    schedule 28.04.2015


Ответы (4)


Вам нужно реализовать UITextFieldDelegate в своем классе и установить этот объект в качестве делегата для UITextField. Затем реализуйте метод textFieldShouldReturn: следующим образом:

func textFieldShouldReturn(textField: UITextField) -> Bool {
    textField.resignFirstResponder()
    if textField == someTextField { // Switch focus to other text field
        otherTextField.becomeFirstResponder()
    }
    return true
}

В вашем примере вам не хватает этой строки:

confirmPasswordTextField.delegate = self

Если вы реализовали делегат, конечно.

person Stefan Salatic    schedule 28.04.2015
comment
А textFieldShouldReturn звонят? - person Stefan Salatic; 28.04.2015
comment
Поэтому у меня возникают некоторые проблемы с ответом, чтобы показать код так, как я хочу, чтобы он отображался. Я установил делегата чуть раньше. Я реализовал UITextFieldDelegate как в MainView, так и в SubView. Я написал код для textFieldShouldReturn, имея на данный момент только println, чтобы увидеть, вызывается ли он либо в MainView, либо в subView... ни один из них не вызывает его. - person Amy Plant; 28.04.2015
comment
Вы должны делать все, что Стефан написал в SignUpWindowView.swift, пока вы создаете там текстовое поле и устанавливаете self в качестве делегата текстового поля. - person Ossir; 28.04.2015
comment
Я отредактировал свой исходный пост, включив в него сокращенную версию SignUpWindowView.swift 1) он показывает реализованный делегат 2) он показывает textfield.delegate=self и 3) он показывает функцию возврата textFieldShould, но я все еще не получаю textFieldShouldReturn для получения вызывается, когда я нажимаю кнопку «Далее» или «Готово» :( - person Amy Plant; 29.04.2015
comment
Вы должны переместить textFieldShouldReturn за пределы drawRect. Таким образом, это внутри функции, а не внутри класса. Протокол не распознает его, и функция не будет вызвана. - person Stefan Salatic; 29.04.2015
comment
Для Swift 3 перед параметрами в функции должен быть символ «_». - person wasimsandhu; 11.05.2017

Я пытался проверить свои текстовые поля в SignUpWindowView.swift, где создаются все текстовые поля. Но, поскольку я помещаю SignUpWindowView в свой MainViewController в качестве подпредставления, вся «обработка» моего UITextField должна выполняться в MainView, а НЕ в его подпредставлении.

Итак, вот весь мой код (на данный момент) для моего MainViewController, который обрабатывает перемещение моего SignUpWindowView вверх/вниз, когда клавиатура отображается/скрывается, а затем перемещается из одного поля в другое. Когда пользователь находится в последнем текстовом поле (чья кнопка «Далее» на клавиатуре теперь установлена ​​​​на «Готово» в подпредставлении), клавиатура убирается, и пользователь может отправить форму с помощью кнопки регистрации.

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)
    }
}
person Amy Plant    schedule 29.04.2015
comment
Эми, вы пропустили вызов super.viewWillDisappear(), который вы, вероятно, хотели бы там (но в остальном хорошая работа). - person gemmakbarlow; 11.05.2015

Использование тегов упрощает задачу. Назначьте теги в порядке возрастания всем текстовым полям, которые вы используете на своем экране.


func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    let textTag = textField.tag+1
    if let nextResponder = textField.superview?.viewWithTag(textTag) as UIResponder
    {
        //textField.resignFirstResponder()
        nextResponder.becomeFirstResponder()
    }
    else {
        // stop editing on pressing the done button on the last text field.

        self.view.endEditing(true)
    }
    return true
}
person PhaniBhushan kolla    schedule 29.12.2017
comment
у меня не работает nextResponder nil все время после self.view.superview?.viewWithTag(textTag) as UIResponder? измени это, это работа для меня - person Harshil Kotecha; 08.05.2018

Вы подключаете событие DidEndOnExit (я написал это по памяти, так что, возможно, это не совсем так, но похоже) UIControl событие, используя @IBAction, и в этой функции вы используете textF.resignFirstResponder() или .becomeFirstResponder()


РЕДАКТИРОВАТЬ

UITextField является подклассом UIControl, и для программного добавления нового события используется метод addTarget(). Бывший:

func a(sender: AnyObject) {}

textField.addTarget(self, action: "a:", forControlEvents: .EditingDidEndOnExit)

документация по UIControl

person Arbitur    schedule 28.04.2015
comment
Как мне сделать это программно в Swift. Я не использую раскадровку для добавления подвида. SignUpWindowView.swift — это класс, который затем добавляется в MainView с помощью кнопки регистрации (то есть в раскадровке), которая запускает функцию, добавляющую подпредставление signUpWindow. Имеет ли это смысл? Я использую бит .becomeFirstResponder... Я просто не могу заставить его распознать функцию textFieldShouldReturn. - person Amy Plant; 28.04.2015