在 Swift 中按下返回键时在文本字段之间切换
Posted
技术标签:
【中文标题】在 Swift 中按下返回键时在文本字段之间切换【英文标题】:Switching between Text fields on pressing return key in Swift 【发布时间】:2015-08-01 22:39:35 【问题描述】:我正在设计一个 ios 应用程序,我希望当我在 iPhone 中按下返回键时,它会将我引导到下一个文本字段。
我发现了几个类似的问题,周围都有很好的答案,但它们都恰好在 Objective-C 中,我正在寻找 Swift 代码,现在这是我到目前为止所拥有的:
func textFieldShouldReturn(emaillabel: UITextField) -> Bool
return true
它被放置在连接到包含文本字段的 UIView 的文件和控制器中,但我不确定那是否是正确的位置。
好的,所以我试了一下,得到了这个错误://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 【参考方案1】:确保您的UITextField
代表已设置并且标签已正确递增。这也可以通过 Interface Builder 完成。
这是我找到的 Obj-C 帖子的链接:How to navigate through textfields (Next / Done Buttons)
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
【讨论】:
我将如何设置它们,我对此很陌生,老实说现在很迷茫 “他们”是指代表。最简单的方法是通过 IB 做到这一点。转到您的故事板->单击每个 UITextField->将委托拖到黄色的 ViewController 图标上。如果您指的是标签,那么您也可以通过 IB 执行此操作。单击每个 UITextField 并设置从 0 开始并以 1 递增的标签。您还可以通过设置 textField.delegate = self 和 textField.tag = n 在 ViewControllers viewDidLoad 中以编程方式设置委托和标签 请发布错误。我进行了编辑并将 UIResponder 更改为 UIResponder! 我添加了一个示例项目的链接。随意看看,如果你解决了,请告诉我。仅供参考:我通过 IB 设置代表和标签。 @meteorSD 有一组文本字段?我不确定这两种做法是否比另一种更好。当主要依赖于 Interface Builder 时,标签似乎是最简单的方法。【参考方案2】:斯威夫特 5
在键盘上单击返回键时,您可以轻松切换到另一个 TextField。
首先,您的视图控制器符合UITextFieldDelegate
,并在ViewController中添加textFieldShouldReturn(_:)
委托方法
在Interface Builder中从TextField拖到ViewController。然后选择delegate
选项。 注意:对所有 TextField 执行此操作
为所有TextFields
创建一个IBOutlet
class ViewController: UIViewController, UITextFieldDelegate
@IBOutlet weak var txtFieldName: UITextField!
@IBOutlet weak var txtFieldEmail: UITextField!
@IBOutlet weak var txtFieldPassword: UITextField!
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
【讨论】:
工作得很好。但是,如果调用 becomeFirstResponder() 时避免使用 resignFirstResponder() 行会很好,因为我的应用程序在键盘移动和返回时会显示一些抽搐。【参考方案3】:我建议你应该在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
【讨论】:
同意,优先办案!【参考方案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
或者只看sample project(xcode 7 beta 4)
【讨论】:
我不太确定我理解坐标部分,你能解释一下吗? 当然。你想从最上面的那个跳到最下面的那个。因此,您按数组中的 y 坐标对其进行排序,因此 array[0] 是顶部的一个,array[1] 是它下面的一个,array[last] 是底部的一个。够了吗? 排序是必要的,因为不能保证文本字段在插座集合中排序:medium.com/@abhimuralidharan/…【参考方案5】:我尝试了很多代码,最后在 Swift 3.0 最新版 [2017 年 3 月]
中对我有用“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”将使键盘返回键显示为“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】:Swift 4.0
中的Caleb版本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?
不适合我
【讨论】:
【参考方案7】:Swift 和编程方式
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
textField.resignFirstResponder() // last textfield, dismiss keyboard directly
return true
【讨论】:
最佳解决方案(比使用标签的公认解决方案更快捷)-完美运行!【参考方案8】:更改为下一个文本字段的最简单方法是无需长代码
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
【讨论】:
【参考方案9】:我对你的问题有一个很好的解决方案。
步骤:
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 的委托。
谢谢你:)
【讨论】:
感谢您的回答。这就是我一直在寻找的。对于那些新的并且可能在关于代表的第 3 点上迷失的人。使用 UITextFieldDelegate 扩展您的课程(您可以查看此问题中的任何其他答案以供您理解)。然后在 viewDidLoad 添加 yourTextFieldName.delegate = self.【参考方案10】:只需在 textFieldShouldReturn
方法中使用 UIResponder 类的 becomeFirstResponder()
方法即可。每个UIView
对象都是UIResponder
的子类。
if self.emaillabel.isEqual(self.anotherTextField)
self.anotherTextField.becomeFirstResponder()
您可以在 Apple Doc 的 here 中找到有关 becomeFirstResponder()
方法的更多信息。
【讨论】:
【参考方案11】:Swift 4.2
这是一个更通用和最简单的解决方案,您可以将此代码与任意数量的 TextField 一起使用。 只需继承UITextFieldDelegate并按照顺序更新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
【讨论】:
以上不适用于 SwiftUI。textFieldNxt
总是不断评估 nil
【参考方案12】:
对于不喜欢使用标签并希望 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
)并按照您的意愿实现该方法。 IE。如果你有不同的单元格类型,那么你可以这样做,同样你可以传入 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()
....
【讨论】:
【参考方案13】:没有什么特别的,这是我目前用来更改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
【讨论】:
【参考方案14】:如果您有很多文本字段组件,最好使用插座集合,链接文本字段并从界面构建器设置返回键
@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
【讨论】:
【参考方案15】:您可以使用字段标签。我认为这比其他更容易。
首先,您必须在此处输入代码,以便为您的字段添加标签。
在我的代码中,usernameField 标记为 0,passwordField 标记为 1。然后我检查了我的标记。然后做进程。
func textFieldShouldReturn(_ textField: UITextField) -> Bool
if textField.tag == 0
passwordField.becomeFirstResponder()
else if textField.tag == 1
self.view.endEditing(true)
loginFunc()
else
print("Hata var")
return false
如果在用户名字段上单击返回,则输入密码。 或者如果您在密码字段时单击返回,请运行登录功能登录。
【讨论】:
【参考方案16】:斯威夫特 4+ 这段代码会对你有所帮助。
class YOURClass: UITextFieldDelegate
override func viewDidLoad()
//delegate your textfield in here
choosenTextField1.delegate = self
choosenTextField2.delegate = self
func textFieldShouldReturn(_ textField: UITextField) -> Bool
switch textField.tag
case 1:
choosenTextField1.becomeFirstResponder()
case 2:
choosenTextField2.becomeFirstResponder()
default:
break
return true
【讨论】:
【参考方案17】:viewWithTag 是一个糟糕的解决方案,因为超级视图可能有带有标签集的视图。这样更好:
public extension Collection where Element: Equatable
func element(after element: Element) -> Element?
guard let index = firstIndex(of: element) else return nil
let nextIndex = self.index(after: index)
return nextIndex < endIndex ? self[nextIndex] : nil
class Controller: UIViewController
@IBOutlet weak var firstNameTextField: UITextField!
@IBOutlet weak var lastNameTextField: UITextField!
@IBOutlet weak var companyTextField: UITextField!
private lazy var primaryTextFields: [UITextField] =
[firstNameTextField, lastNameTextField, companyTextField]
()
override func viewDidLoad()
super.viewDidLoad()
primaryTextFields.forEach $0.delegate = self
extension Controller: UITextFieldDelegate
func textFieldShouldReturn(_ textField: UITextField) -> Bool
if let next = primaryTextFields.element(after: textField)
next.becomeFirstResponder()
else if primaryTextFields.contains(textField)
textField.resignFirstResponder()
return true
【讨论】:
以上是关于在 Swift 中按下返回键时在文本字段之间切换的主要内容,如果未能解决你的问题,请参考以下文章
按下返回键时如何在下一个 UITextField 上移动控件