【问题标题】:Next/Done button using Swift with textFieldShouldReturn使用带有 textFieldShouldReturn 的 Swift 的 Next/Done 按钮
【发布时间】:2015-04-28 17:15:46
【问题描述】:

我有一个 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

我的问题是我正在尝试配置键盘上的下一步/完成按钮,但不确定要添加 textFieldShouldReturn 功能的哪个视图(MainViewSignUpWindowView)。我已经尝试了这两种方法,但甚至无法触发println 来测试该函数是否正在执行。一旦我让textFieldShouldReturn 触发,我相信我可以执行必要的代码来让 Next/Done 按钮做我想做的事情,并将发布包含 Next/Done 功能的最终解决方案。

更新为包含 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()
}

【问题讨论】:

  • 您将什么设置为文本字段委托?
  • confirmPasswordTextField.delegate=self

标签: ios swift xcode6 subview uitextfielddelegate


【解决方案1】:

您需要在您的类中实现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

当然,如果你已经实现了委托。

【讨论】:

  • textFieldShouldReturn 会被调用吗?
  • 所以我在回复以我希望的方式显示代码时遇到了一些问题。我已经设置了代表,就在前面。我确实在 MainView 和 SubView 中实现了 UITextFieldDelegate。我为 textFieldShouldReturn 编写了代码,目前只有一个 println 来查看它是否在 MainView 或 subView 中被调用......两者都没有调用它。
  • 你应该做 Stefan 在SignUpWindowView.swift 中写的所有事情,只要你在那里创建文本字段并将self 设置为文本字段委托
  • 我编辑了我的原始帖子以包含 SignUpWindowView.swift 的缩写版本 1) 它显示了已实现的委托 2) 它显示了 textfield.delegate=self 和 3) 它显示了 textFieldShould 返回函数但我仍然当我点击下一个或完成按钮时,不要调用 textFieldShouldReturn :(
  • 您必须将 textFieldShouldReturn 移到 drawRect 之外。这样它就在函数内部而不是在类内部。协议不会识别它,函数也不会被调用。
【解决方案2】:

我试图在 SignUpWindowView.swift 中测试我的文本字段,这是创建所有文本字段的地方。但是,由于我将 SignUpWindowView 作为子视图放入 MainViewController 中,因此我的所有 UITextField“处理”都需要在 MainView 而不是它的子视图中完成。

这是我的 MainViewController 的全部代码(目前),它处理在显示/隐藏键盘时向上/向下移动我的 SignUpWindowView,然后从一个字段移动到下一个字段。当用户位于最后一个文本字段(其键盘 Next 按钮现在在子视图中设置为 Done)时,键盘会收起,然后用户可以使用注册按钮提交表单。

主视图控制器:

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

【讨论】:

  • 艾米,你错过了对 super.viewWillDisappear() 的调用,你可能想要在那里(但其他方面做得很好)。
【解决方案3】:

使用标签更容易。为您在屏幕上使用的所有文本字段按升序分配标签。


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
}

【讨论】:

  • 在 self.view.superview?.viewWithTag(textTag) 作为 UIResponder 之后,它对我的​​ nextResponder nil 一直不起作用?改变它对我有用
【解决方案4】:

您使用@IBAction 连接DidEndOnExit(我是从内存中写的,所以它可能不完全称为但类似)UIControl 事件,并且在该函数中您使用textF.resignFirstResponder().becomeFirstResponder()


编辑

UITextField 是 UIControl 的子类,要以编程方式添加新事件,请使用 addTarget() 方法。例如:

func a(sender: AnyObject) {}

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

UIControl docs

【讨论】:

  • 如何在 Swift 中以编程方式完成。我没有使用情节提要来添加子视图。 SignUpWindowView.swift 是一个类,然后通过一个注册按钮(在故事板中)添加到 MainView,该按钮运行一个添加 signUpWindow 子视图的函数。那有意义吗?我开始使用 .becomeFirstResponder 位......我似乎无法让它识别 textFieldShouldReturn 函数。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-03-14
  • 2011-08-01
  • 2013-11-25
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多