Подтвердить что ты не робот

Переключение между текстовыми полями при нажатии клавиши возврата в Swift

Я разрабатываю приложение для iOS и хочу, чтобы при нажатии клавиши возврата в моем iPhone он направлял меня в следующее текстовое поле.

Я нашел пару похожих вопросов, с отличными ответами, но все они просто в Objective-C, и я ищу код Swift, теперь это то, что у меня есть до сих пор:

func textFieldShouldReturn(emaillabel: UITextField) -> Bool{
    return true
}

Он помещен в файл, который подключен и контролирует к UIView, который содержит текстовые поля, но я не уверен, что это правильное место.

Я в основном новичок в Swift, поэтому объясните каждый маленький шаг, или мне удастся как-то испортить его. Также я использую последнюю версию XCode, если это имеет какое-либо значение.

Итак, я попробовал это и получил эту ошибку:
//could not find an overload for '!=' that accepts the supplied arguments

func textFieldShouldReturn(textField: UITextField) -> Bool {
    let nextTag: NSInteger = textField.tag + 1
    // Try to find next responder
    let nextResponder: UIResponder = textField.superview!.viewWithTag(nextTag)!
    if (nextResponder != nil) {
        // could not find an overload for '!=' that accepts the supplied arguments

        // Found next responder, so set it.
        nextResponder.becomeFirstResponder()
    } else {
        // Not found, so remove keyboard.
        textField.resignFirstResponder()
    }
    return false // We do not want UITextField to insert line-breaks.
}

Заранее спасибо, друзья!

4b9b3361

Ответ 1

Убедитесь, что ваши делегаты UITextField установлены и теги правильно увеличены. Это также можно сделать через Интерфейсный Разработчик.

Вот ссылка на сообщение об Obj-C, которое я нашел: Как перемещаться по текстовым полям (кнопки "Далее"/"Готово")

class ViewController: UIViewController,UITextFieldDelegate {
   // Link each UITextField (Not necessary if delegate and tag are set in Interface Builder)
   @IBOutlet weak var someTextField: UITextField!

   override func viewDidLoad() {
      super.viewDidLoad()
      // Do the next two lines for each UITextField here or in the Interface Builder
      someTextField.delegate = self
      someTextField.tag = 0 //Increment accordingly
   }

   func textFieldShouldReturn(_ textField: UITextField) -> Bool {
      // Try to find next responder
      if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {
         nextField.becomeFirstResponder()
      } else {
         // Not found, so remove keyboard.
         textField.resignFirstResponder()
      }
      // Do not add a line break
      return false
   }
}

Ответ 2

Swift 5

Вы можете легко переключиться на другое TextField, нажав клавишу возврата на клавиатуре.

  • Во-первых, ваш контроллер представления соответствует UITextFieldDelegate и добавляет делегированный метод textFieldShouldReturn(_:) в ViewController.
  • Перетащите из TextField в ViewController в Интерфейсном Разработчике. Затем выберите опцию delegate. Примечание: сделать это для всех TextField
  • Создать IBOutlet для всех TextFields

    class ViewController: UIViewController, UITextFieldDelegate {
    
      @IBOutlet weak var txtFieldName: UITextField!
      @IBOutlet weak var txtFieldEmail: UITextField!
      @IBOutlet weak var txtFieldPassword: UITextField!
    
      override func viewDidLoad() {
        super.viewDidLoad()
    
      }
    
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField == txtFieldName {
           textField.resignFirstResponder()
           txtFieldEmail.becomeFirstResponder()
        } else if textField == txtFieldEmail {
           textField.resignFirstResponder()
           txtFieldPassword.becomeFirstResponder()
        } else if textField == txtFieldPassword {
           textField.resignFirstResponder()
        }
       return true
      }
    }
    

Ответ 3

Я предлагаю вам использовать оператор switch в textFieldShouldReturn(_:).

// MARK: UITextFieldDelegate

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    switch textField {
    case nameTextField:
        phoneTextField.becomeFirstResponder()
    case phoneTextField:
        emailTextField.becomeFirstResponder()
    case emailTextField:
        descriptionTextField.becomeFirstResponder()
    default:
        textField.resignFirstResponder()
    }
    return false
}

Ответ 4

Этот подход нуждается в некоторых изменениях в представлениях таблиц и представлениях коллекции, но это нормально для простых форм, я думаю.

Подключите textFields к одному IBOutletCollection, отсортируйте его по координате y и в textFieldShouldReturn(_:) просто перейдите к следующему текстовому полю, пока не достигнете конца:

@IBOutlet var textFields: [UITextField]!

...

textFields.sortInPlace { $0.frame.origin.y < $1.frame.origin.y }

...

func textFieldShouldReturn(textField: UITextField) -> Bool {
    if let currentIndex = textFields.indexOf(textField) where currentIndex < textFields.count-1 {
        textFields[currentIndex+1].becomeFirstResponder()
    } else {
        textField.resignFirstResponder()
    }
    return true
}    

Или просто посмотрите образец проекта (xcode 7 beta 4)

Ответ 5

Я пробовал много кодов, и, наконец, это сработало для меня в Swift 3.0 Latest [March 2017]

Класс "ViewController" должен унаследовать "UITextFieldDelegate" для создания этого кода.

class ViewController: UIViewController,UITextFieldDelegate  

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

override func viewDidLoad() {

 userNameTextField.delegate = self

        userNameTextField.tag = 0

        userNameTextField.returnKeyType = UIReturnKeyType.next

        passwordTextField.delegate = self

        passwordTextField.tag = 1


        passwordTextField.returnKeyType = UIReturnKeyType.go

}

В вышеприведенном коде "returnKeyType = UIReturnKeyType.next", где будет отображаться клавиша возврата клавиши Key, как "Next", у вас также есть другие опции, такие как "Join/Go" и т.д., на основе вашего приложения изменяют значения.

Этот "textFieldShouldReturn" - это метод управления UITextFieldDelegate, и здесь мы имеем следующий выбор полей, основанный на добавлении значения тега

func textFieldShouldReturn(_ textField: UITextField) -> Bool

    {

        if let nextField = textField.superview?.viewWithTag(textField.tag + 1) as? UITextField {

            nextField.becomeFirstResponder()

        } else {

            textField.resignFirstResponder()

            return true;

        }

        return false

    }

Ответ 6

Самый простой способ перейти к следующему текстовому полю - это отсутствие необходимости в длинном коде

override func viewDidLoad() {
        super.viewDidLoad()

        emailTextField.delegate = self
        passwordTextField.delegate = self
    }


    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField == emailTextField {
            passwordTextField.becomeFirstResponder()
        }else {
            passwordTextField.resignFirstResponder()
        }
            return true
    }

Ответ 7

Версия Калеба в Swift 4.0

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if let nextField = self.view.viewWithTag(textField.tag + 1) as? UITextField {
        nextField.becomeFirstResponder()
    } else {
        textField.resignFirstResponder()
    }
    return false
}

PS textField.superview? не работает для меня

Ответ 8

Просто используйте метод becomeFirstResponder() класса UIResponder в вашем методе textFieldShouldReturn. Каждый объект UIView представляет собой подклассы UIResponder.

if self.emaillabel.isEqual(self.anotherTextField)
{
    self.anotherTextField.becomeFirstResponder()
}

Дополнительную информацию о методе becomeFirstResponder() в Apple Doc можно найти в здесь.

Ответ 9

Swift 4.2

Это более общее и простое решение, вы можете использовать этот код с любым количеством TextFields. Просто наследуйте UITextFieldDelegate и обновите тег Textfield в соответствии с порядком и скопируйте эту функцию

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    let txtTag:Int = textField.tag

    if let textFieldNxt = self.view.viewWithTag(txtTag+1) as? UITextField {
        textFieldNxt.becomeFirstResponder()
    }else{
        textField.resignFirstResponder()
    }

    return true
}

Ответ 10

Свифт/Программно

class MyViewController: UIViewController, UITextFieldDelegate {

    let textFieldA = UITextField()
    let textFieldB = UITextField()
    let textFieldC = UITextField()
    let textFieldD = UITextField()

    var textFields: [UITextField] {
        return [textFieldA, textFieldB, textFieldC, textFieldD]
    }

    override func viewDidLoad() {
        // layout textfields somewhere 
        // then set delegate
        textFields.forEach { $0.delegate = self }
    }

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if let selectedTextFieldIndex = textFields.firstIndex(of: textField), selectedTextFieldIndex < textFields.count - 1 {
            textFields[selectedTextFieldIndex + 1].becomeFirstResponder()
        } else {
            view.endEditing(true) // last textfield, dismiss keyboard directly
        }
        return true
    }
}

Ответ 11

Альтернативный метод для пуристов, которым не нравится использовать теги, и хочет, чтобы делегат UITextField был ячейкой, чтобы компоненты были разделены или однонаправленны...

  • Создайте новый протокол, чтобы связать Cell и TableViewController.

    protocol CellResponder {
      func setNextResponder(_ fromCell: UITableViewCell)
    }
    
  • Добавьте протокол в свою ячейку, где ваш делегат TextField также является ячейкой (я делаю это в раскадровке).

    class MyTableViewCell: UITableViewCell, UITextFieldDelegate {
      var responder: CellResponder?
    
      func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        responder?.setNextResponder(self)
        return true
      }
    }
    
  • Сделайте свой TableViewController совместимым с протоколом CellResponder (т.е. class MyTableViewController: UITableViewController, CellResponder) и реализуйте метод по своему усмотрению. То есть если у вас разные типы ячеек, вы могли бы это сделать, также вы могли бы пройти в IndexPath, использовать тег и т.д. Не забудьте установить cell.responder = self в cellForRow..

    func setNextResponder(_ fromCell: UITableViewCell) {
      if fromCell is MyTableViewCell, let nextCell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? MySecondTableViewCell {
    
        nextCell.aTextField?.becomeFirstResponder()
    
      } ....
    }
    

Ответ 12

Ничего особенного, вот мой в настоящее время используется для изменения textFiled. Таким образом, код в ViewController выглядит хорошо :). # Swift4

final class SomeTextFiled: UITextField {

  public var actionKeyboardReturn: (() -> ())?

  override init(frame: CGRect) {
      super.init(frame: frame)
      super.delegate = self
  }

  required init?(coder aDecoder: NSCoder) {
      super.init(coder: aDecoder)
      fatalError("init(coder:) has not been implemented")
  }

  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
      self.resignFirstResponder()
      actionKeyboardReturn?()
      return true
   }
}

extension SomeTextFiled: UITextFieldDelegate {}


class MyViewController : UIViewController {

    var tfName: SomeTextFiled!
    var tfEmail: SomeTextFiled!
    var tfPassword: SomeTextFiled!

    override func viewDidLoad() {
        super.viewDidLoad()
        tfName = SomeTextFiled(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        tfName.actionKeyboardReturn = { [weak self] in
            self?.tfEmail.becomeFirstResponder()
        }
        tfEmail = SomeTextFiled(frame: CGRect(x: 100, y: 0, width: 100, height: 100))
        tfEmail.actionKeyboardReturn = { [weak self] in
            self?.tfPassword.becomeFirstResponder()
        }
        tfPassword = SomeTextFiled(frame: CGRect(x: 200, y: 0, width: 100, height: 100))
        tfPassword.actionKeyboardReturn = {
            /// Do some further code
        }
    }
}

Ответ 13

Если у вас много компонентов текстового поля, может быть лучше использовать коллекцию розеток, связать текстовые поля и установить Return Key от конструктора интерфейса

@IBOutlet var formTextFields: [UITextField]!

override func viewDidLoad() {
  for textField in formTextFields {
    textField.delegate = self
  }
}

extension RegisterViewController: UITextFieldDelegate {
  func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    if let componentIndex = formTextFields.firstIndex(of: textField) {
      if textField.returnKeyType == .next,
        componentIndex < (formTextFields.count - 1) {
        formTextFields[componentIndex + 1].becomeFirstResponder()
      } else {
        textField.resignFirstResponder()
      }
    }
    return true
  }
}

Ответ 14

У меня есть хорошее решение для вашего вопроса.

ШАГ:

1 - Установите ключ возврата из раскадровки.

enter image description here

2 - В вашем быстром файле.

func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        if textField.returnKeyType == .next {
            Email.resignFirstResponder()
            Password.becomeFirstResponder()
        } else if textField.returnKeyType == .go {
            Password.resignFirstResponder()
            self.Login_Action()
        }
        return true
    }

3 - Не забудьте установить делегат текстового поля.

Спасибо :)