IOSアプリを設計していますが、iPhoneでReturnキーを押すと、次のテキストフィールドに移動するようになります。
私はいくつかの同様の質問を見つけましたが、周りには優れた答えがありますが、それらはすべて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.
}
事前の仲間に感謝します!
UITextField
デリゲートが設定され、タグが適切にインクリメントされていることを確認してください。これは、Interface Builderでも実行できます。
ここに私が見つけた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
}
}
Swift 5
キーボードのReturnキーをクリックすると、別のTextFieldに簡単に切り替えることができます。
UITextFieldDelegate
に準拠し、ViewControllerにtextFieldShouldReturn(_:)
デリゲートメソッドを追加します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
}
}
textFieldShouldReturn(_:)
でswitchステートメントを使用することをお勧めします。
// 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
}
このアプローチでは、テーブルビューとコレクションビューを多少変更する必要がありますが、単純なフォームでは問題ありません。
textFields
を1つの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)を見てください
私は多くのコードを試してみましたが、最終的にこれはSwift 3.0 Latest [March 2017]
このコードを機能させるために、「ViewController」クラスは「UITextFieldDelegate」を継承する必要があります。
class ViewController: UIViewController,UITextFieldDelegate
適切なタグnuberでテキストフィールドを追加し、このタグ番号を使用して、割り当てられた増分タグ番号に基づいて適切なテキストフィールドにコントロールを取得します。
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」でキーパッドのリターンキーを「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
}
次のテキストフィールドに変更する最も簡単な方法は、長いコードが必要ないことです
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
}
カレブバージョンSwift 4.
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = self.view.viewWithTag(textField.tag + 1) as? UITextField {
nextField.becomeFirstResponder()
} else {
textField.resignFirstResponder()
}
return false
}
追伸textField.superview?
が機能していません
Swift 4.2
これはより一般的で最も簡単なソリューションであり、このコードは任意の量のTextFieldで使用できます。 ITextFieldDelegateを継承し、順序に従ってTextfield Tagを更新して、この関数をコピーするだけです。
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
}
textFieldShouldReturn
メソッドでUIResponderクラスのbecomeFirstResponder()
メソッドを使用するだけです。すべてのUIView
オブジェクトはUIResponder
のサブクラスです。
if self.emaillabel.isEqual(self.anotherTextField)
{
self.anotherTextField.becomeFirstResponder()
}
becomeFirstResponder()
メソッドの詳細については、[ here のApple Docにあります。
スイフト/プログラム
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
}
}
テキストフィールドコンポーネントがたくさんある場合は、アウトレットコレクションを使用して、テキストフィールドをリンクし、インターフェイスビルダーからリターンキーを設定する方が良いかもしれません
@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
}
}
特別なことはありません。ここでは、テキストフィールドを変更するために現在使用しています。 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
}
}
}
タグの使用を好まない純粋主義者向けの代替メソッドであり、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を渡したり、タグを使用したりすることができます。cellForRowにcell.responder = self
を設定することを忘れないでください。
func setNextResponder(_ fromCell: UITableViewCell) {
if fromCell is MyTableViewCell, let nextCell = tableView.cellForRow(at: IndexPath(row: 1, section: 0)) as? MySecondTableViewCell {
nextCell.aTextField?.becomeFirstResponder()
} ....
}
あなたの質問には良い解決策があります。
STEP:
1-ストーリーボードからリターンキーを設定します。
2-Swiftファイル内。
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-Textfieldのデリゲートを設定することを忘れないでください。
ありがとうございました :)