phx*_*phx 480 iphone objective-c ios
如何使用iPhone键盘上的"下一步"按钮浏览所有文本字段?
最后一个文本字段应该关闭键盘.
我已经设置了IB按钮(下一个/完成),但现在我被卡住了.
我实现了textFieldShouldReturn操作,但现在Next和Done Buttons关闭了Keyboard.
Pey*_*loW 573
在Cocoa for Mac OS X中,您有下一个响应者链,您可以在其中询问文本字段接下来应该关注哪个控件.这就是使文本字段之间的标签工作的原因.但由于iOS设备没有键盘,只有触摸,这个概念还没有幸免于过渡到Cocoa Touch.
无论如何,这可以轻松完成,有两个假设:
UITextField都在同一个父视图中.假设你可以覆盖textFieldShouldReturn:如下:
-(BOOL)textFieldShouldReturn:(UITextField*)textField
{
NSInteger nextTag = textField.tag + 1;
// Try to find next responder
UIResponder* nextResponder = [textField.superview viewWithTag:nextTag];
if (nextResponder) {
// Found next responder, so set it.
[nextResponder becomeFirstResponder];
} else {
// Not found, so remove keyboard.
[textField resignFirstResponder];
}
return NO; // We do not want UITextField to insert line-breaks.
}
Run Code Online (Sandbox Code Playgroud)
添加更多代码,也可以忽略这些假设.
Swift 4.0
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
// Try to find next responder
let nextResponder = textField.superview?.viewWithTag(nextTag) as UIResponder!
if nextResponder != nil {
// Found next responder, so set it
nextResponder?.becomeFirstResponder()
} else {
// Not found, so remove keyboard
textField.resignFirstResponder()
}
return false
}
Run Code Online (Sandbox Code Playgroud)
如果文本字段的超级视图将是UITableViewCell,则下一个响应者将是
let nextResponder = textField.superview?.superview?.superview?.viewWithTag(nextTag) as UIResponder!
Run Code Online (Sandbox Code Playgroud)
mem*_*ons 170
还有一个很多更优雅的解决方案,它把我吓倒了,我第一次看到它.优点:
UITextField和UITextView控件 - 或任何键盘输入UI控件创建一个UITextField子类,它具有一个IBOutlet名为nextField 的属性.这是标题:
@interface SOTextField : UITextField
@property (weak, nonatomic) IBOutlet UITextField *nextField;
@end
Run Code Online (Sandbox Code Playgroud)
这是实施:
@implementation SOTextField
@end
Run Code Online (Sandbox Code Playgroud)
在视图控制器中,您将创建-textFieldShouldReturn:委托方法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField {
if ([textField isKindOfClass:[SOTextField class]]) {
UITextField *nextField = [(SOTextField *)textField nextField];
if (nextField) {
dispatch_async(dispatch_get_current_queue(), ^{
[nextField becomeFirstResponder];
});
}
else {
[textField resignFirstResponder];
}
}
return YES;
}
Run Code Online (Sandbox Code Playgroud)
在IB中,更改您的UITextField以使用SOTextField该类.其次,也是在IB,设置每个"SOTextFields'to'文件的所有者’(你把代码的委托方法是正确的- textFieldShouldReturn)的代表.这种设计的优点在于,现在您只需右键单击任何textField,并将nextField出口分配给SOTextField您希望成为下一个响应者的下一个对象.

此外,你可以做很酷的事情,比如循环textFields,这样在最后一个失去焦点后,第一个会再次获得焦点.
这可以很容易地扩展到自动分配returnKeyType的SOTextField一个UIReturnKeyNext,如果有分配nextField -少了一个东西手动配置.
mxc*_*xcl 80
这是一个没有代表团的人:
tf1.addTarget(tf2, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
tf2.addTarget(tf3, action: #selector(becomeFirstResponder), for: .editingDidEndOnExit)
Run Code Online (Sandbox Code Playgroud)
ObjC:
[tf1 addTarget:tf2 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
[tf2 addTarget:tf3 action:@selector(becomeFirstResponder) forControlEvents:UIControlEventEditingDidEndOnExit];
Run Code Online (Sandbox Code Playgroud)
使用(主要是未知的)UIControlEventEditingDidEndOnExit UITextField动作.
您还可以轻松地将其连接到故事板中,因此不需要委托或代码.
编辑:实际上我无法弄清楚如何在故事板中将其连接起来.becomeFirstResponder似乎不是这个控制事件的提议行动,这是一个遗憾.仍然,您可以将所有文本字段挂钩到ViewController中的单个操作,然后确定哪个textField becomeFirstResponder基于发件人(尽管它不像上面的编程解决方案那样优雅,因此IMO使用上面的代码执行viewDidLoad).
Ant*_*th0 78
这是我解决这个问题的方法.
为了解决这个问题(因为我讨厌依靠标签做的东西),我决定自定义属性添加到UITextField对象.换句话说,我在UITextField上创建了一个类别,如下所示:
的UITextField + Extended.h
@interface UITextField (Extended)
@property(retain, nonatomic)UITextField* nextTextField;
@end
Run Code Online (Sandbox Code Playgroud)
的UITextField + Extended.m
#import "UITextField+Extended.h"
#import <objc/runtime.h>
static char defaultHashKey;
@implementation UITextField (Extended)
- (UITextField*) nextTextField {
return objc_getAssociatedObject(self, &defaultHashKey);
}
- (void) setNextTextField:(UITextField *)nextTextField{
objc_setAssociatedObject(self, &defaultHashKey, nextTextField, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
Run Code Online (Sandbox Code Playgroud)
现在,这是我如何使用它:
UITextField *textField1 = ...init your textfield
UITextField *textField2 = ...init your textfield
UITextField *textField3 = ...init your textfield
textField1.nextTextField = textField2;
textField2.nextTextField = textField3;
textField3.nextTextField = nil;
Run Code Online (Sandbox Code Playgroud)
并实现textFieldShouldReturn方法:
- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {
UITextField *next = theTextField.nextTextField;
if (next) {
[next becomeFirstResponder];
} else {
[theTextField resignFirstResponder];
}
return NO;
}
Run Code Online (Sandbox Code Playgroud)
我现在有一个UITextField的链接列表,每个人都知道谁在下一行.
希望它会有所帮助.
Amo*_*hua 46
一个快速扩展,应用mxcl的答案,使这特别容易(适应旅行者swift 2.3):
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for i in 0 ..< fields.count - 1 {
fields[i].returnKeyType = .Next
fields[i].addTarget(fields[i+1], action: "becomeFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
last.returnKeyType = .Done
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), forControlEvents: .EditingDidEndOnExit)
}
}
Run Code Online (Sandbox Code Playgroud)
它易于使用:
UITextField.connectFields([field1, field2, field3])
Run Code Online (Sandbox Code Playgroud)
对于除最后一个字段之外的所有字段,扩展名将返回按钮设置为"下一个",对于最后一个字段,将"返回"设置为"完成",并在点击这些字段时切换焦点/关闭键盘.
斯威夫特<2.3
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for var i = 0; i < fields.count - 1; i += 1 {
fields[i].returnKeyType = .Next
fields[i].addTarget(fields[i+1], action: "becomeFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
last.returnKeyType = .Done
last.addTarget(last, action: "resignFirstResponder", forControlEvents: .EditingDidEndOnExit)
}
}
Run Code Online (Sandbox Code Playgroud)
SWIFT 3: 像这样使用 -
UITextField.connectFields(fields: [field1, field2])
Extension:
extension UITextField {
class func connectFields(fields:[UITextField]) -> Void {
guard let last = fields.last else {
return
}
for i in 0 ..< fields.count - 1 {
fields[i].returnKeyType = .next
fields[i].addTarget(fields[i+1], action: #selector(UIResponder.becomeFirstResponder), for: .editingDidEndOnExit)
}
last.returnKeyType = .go
last.addTarget(last, action: #selector(UIResponder.resignFirstResponder), for: .editingDidEndOnExit)
}
}
Run Code Online (Sandbox Code Playgroud)
moh*_*945 25
更一致和更健壮的方法是使用NextResponderTextField
您可以完全从界面构建器配置它,而无需设置委托或使用view.tag.
你需要做的就是
UITextField是NextResponderTextField

nextResponderField指向下一个响应者的出口,它可以是UITextField任何子UIResponder类或任何子类.它也可以是一个UIButton,并且该库足够智能,TouchUpInside只有在启用时才触发按钮事件.

这是图书馆的行动:

Mar*_*uee 14
我喜欢Anth0和Answerbot已经提出过的OO解决方案.但是,我正在开发一个快速小巧的POC,所以我不想让子类和类别混乱.
另一个简单的解决方案是创建一个NSArray字段,并在按下下一个字段时查找下一个字段.不是OO解决方案,但快速,简单且易于实施.此外,您可以一目了然地查看和修改订购.
这是我的代码(基于此线程中的其他答案):
@property (nonatomic) NSArray *fieldArray;
- (void)viewDidLoad {
[super viewDidLoad];
fieldArray = [NSArray arrayWithObjects: firstField, secondField, thirdField, nil];
}
- (BOOL) textFieldShouldReturn:(UITextField *) textField {
BOOL didResign = [textField resignFirstResponder];
if (!didResign) return NO;
NSUInteger index = [self.fieldArray indexOfObject:textField];
if (index == NSNotFound || index + 1 == fieldArray.count) return NO;
id nextField = [fieldArray objectAtIndex:index + 1];
activeField = nextField;
[nextField becomeFirstResponder];
return NO;
}
Run Code Online (Sandbox Code Playgroud)
pic*_*ano 11
这是使用UIControl上的类别进行Tab键的实现.这个解决方案具有Michael和Anth0方法的所有优点,但适用于所有UIControl,而不仅仅是UITextFields.它还可以与Interface Builder和故事板无缝协作.
源和示例应用程序:UIControlsWithTabbing的GitHub存储库
用法:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
[textField transferFirstResponderToNextControl];
return NO;
}
Run Code Online (Sandbox Code Playgroud)

标题:
//
// UIControl+NextControl.h
// UIControlsWithTabbing
//
#import <UIKit/UIKit.h>
@interface UIControl (NextControl)
@property (nonatomic, weak) IBOutlet UIControl *nextControl;
- (BOOL)transferFirstResponderToNextControl;
@end
Run Code Online (Sandbox Code Playgroud)
执行:
#import "UIControl+NextControl.h"
#import <objc/runtime.h>
static char defaultHashKey;
@implementation UIControl (NextControl)
- (UIControl *)nextControl
{
return objc_getAssociatedObject(self, &defaultHashKey);
}
- (void)setNextControl:(UIControl *)nextControl
{
objc_setAssociatedObject(self, &defaultHashKey, nextControl, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
- (BOOL)transferFirstResponderToNextControl
{
if (self.nextControl)
{
[self.nextControl becomeFirstResponder];
return YES;
}
[self resignFirstResponder];
return NO;
}
@end
Run Code Online (Sandbox Code Playgroud)
BHU*_*MAR 10
我尝试了很多代码,最后,这在Swift 3.0中为我工作最新[2017年3月]
该ViewController班应该继承了UITextFieldDelegate制作该代码工作.
class ViewController: UIViewController,UITextFieldDelegate
Run Code Online (Sandbox Code Playgroud)
添加带有正确标记号的文本字段,此标记号用于根据分配给它的增量标记号将控件转移到适当的文本字段.
override func viewDidLoad() {
userNameTextField.delegate = self
userNameTextField.tag = 0
userNameTextField.returnKeyType = UIReturnKeyType.next
passwordTextField.delegate = self
passwordTextField.tag = 1
passwordTextField.returnKeyType = UIReturnKeyType.go
}
Run Code Online (Sandbox Code Playgroud)
在上面的代码中,returnKeyType = UIReturnKeyType.nextwhere将使键盘返回键显示,因为Next您还有其他选项Join/Go等,根据您的应用程序更改值.
这 textFieldShouldReturn是一个UITextFieldDelegate控制的方法,这里我们根据Tag值增量进行下一个字段选择
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
}
Run Code Online (Sandbox Code Playgroud)
退出一个文本字段后,调用[otherTextField becomeFirstResponder],下一个字段获得焦点.
这实际上可能是一个棘手的问题,因为您通常还需要滚动屏幕或以其他方式调整文本字段的位置,以便在编辑时很容易看到.只需确保以不同的方式进出文本字段并进行大量测试,并提前离开(总是让用户选择关闭键盘而不是去下一个字段,通常使用"完成"导航栏)
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
[[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
return YES;
}
Run Code Online (Sandbox Code Playgroud)
按下"完成"按钮时,解除键盘的一种非常简单的方法是:
在标题中创建一个新的IBAction
- (IBAction)textFieldDoneEditing:(id)sender;
Run Code Online (Sandbox Code Playgroud)
在实现文件(.m文件)中添加以下方法:
- (IBAction)textFieldDoneEditing:(id)sender
{
[sender resignFirstResponder];
}
Run Code Online (Sandbox Code Playgroud)
然后,当您将IBAction链接到文本字段时 - 链接到"退出时结束"事件.
我很惊讶这里有多少答案无法理解一个简单的概念:浏览应用程序中的控件并不是视图本身应该做的事情.这是控制器的工作,以决定哪些控制,使下一个第一响应者.
此外,大多数答案仅适用于向前导航,但用户可能也想要倒退.
所以这就是我想出来的.您的表单应由视图控制器管理,视图控制器是响应程序链的一部分.所以你可以完全自由地实现以下方法:
#pragma mark - Key Commands
- (NSArray *)keyCommands
{
static NSArray *commands;
static dispatch_once_t once;
dispatch_once(&once, ^{
UIKeyCommand *const forward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:0 action:@selector(tabForward:)];
UIKeyCommand *const backward = [UIKeyCommand keyCommandWithInput:@"\t" modifierFlags:UIKeyModifierShift action:@selector(tabBackward:)];
commands = @[forward, backward];
});
return commands;
}
- (void)tabForward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.firstObject becomeFirstResponder];
}
- (void)tabBackward:(UIKeyCommand *)command
{
NSArray *const controls = self.controls;
UIResponder *firstResponder = nil;
for (UIResponder *const responder in controls.reverseObjectEnumerator) {
if (firstResponder != nil && responder.canBecomeFirstResponder) {
[responder becomeFirstResponder]; return;
}
else if (responder.isFirstResponder) {
firstResponder = responder;
}
}
[controls.lastObject becomeFirstResponder];
}
Run Code Online (Sandbox Code Playgroud)
可以应用用于预先滚动屏幕外响应者的附加逻辑.
这种方法的另一个好处是,你并不需要继承各种控件,你可能想要显示(如UITextFieldS),但在控制器级别,其中,说实话可以代替管理逻辑,是在正确的地方这样做.
小智 6
首先在xib中设置键盘返回键,否则你可以编写代码viewdidload:
passWord.returnKeyType = UIReturnKeyNext;
-(BOOL)textFieldShouldReturn:(UITextField *)textField
{
if(textField == eMail) {
[textField resignFirstResponder];
[userName becomeFirstResponder];
}
if (textField==userName) {
[textField resignFirstResponder];
[passWord becomeFirstResponder];
}
if (textField==passWord) {
[textField resignFirstResponder];
[country becomeFirstResponder];
}
if (textField==country) {
[textField resignFirstResponder];
}
return YES;
}
Run Code Online (Sandbox Code Playgroud)
Swift 3.1 中的解决方案,在连接文本字段 IBOutlets 后,在 viewDidLoad 中设置文本字段委托,然后在 textFieldShouldReturn 中导航您的操作
class YourViewController: UIViewController,UITextFieldDelegate {
@IBOutlet weak var passwordTextField: UITextField!
@IBOutlet weak var phoneTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
self.passwordTextField.delegate = self
self.phoneTextField.delegate = self
// Set your return type
self.phoneTextField.returnKeyType = .next
self.passwordTextField.returnKeyType = .done
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool{
if textField == self.phoneTextField {
self.passwordTextField.becomeFirstResponder()
}else if textField == self.passwordTextField{
// Call login api
self.login()
}
return true
}
}
Run Code Online (Sandbox Code Playgroud)
如果有人想要这样。我认为这是最接近所要求的要求
这是我如何实施这个
为您想要设置的每个文本字段添加附件视图,使用
func setAccessoryViewFor(textField : UITextField) {
let toolBar = UIToolbar()
toolBar.barStyle = .default
toolBar.isTranslucent = true
toolBar.sizeToFit()
// Adds the buttons
// Add previousButton
let prevButton = UIBarButtonItem(title: "<", style: .plain, target: self, action: #selector(previousPressed(sender:)))
prevButton.tag = textField.tag
if getPreviousResponderFor(tag: textField.tag) == nil {
prevButton.isEnabled = false
}
// Add nextButton
let nextButton = UIBarButtonItem(title: ">", style: .plain, target: self, action: #selector(nextPressed(sender:)))
nextButton.tag = textField.tag
if getNextResponderFor(tag: textField.tag) == nil {
nextButton.title = "Done"
}
let spaceButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)
toolBar.setItems([prevButton,spaceButton,nextButton], animated: false)
toolBar.isUserInteractionEnabled = true
textField.inputAccessoryView = toolBar
}
Run Code Online (Sandbox Code Playgroud)
使用以下函数来处理水龙头
func nextPressed(sender : UIBarButtonItem) {
if let nextResponder = getNextResponderFor(tag: sender.tag) {
nextResponder.becomeFirstResponder()
} else {
self.view.endEditing(true)
}
}
func previousPressed(sender : UIBarButtonItem) {
if let previousResponder = getPreviousResponderFor(tag : sender.tag) {
previousResponder.becomeFirstResponder()
}
}
func getNextResponderFor(tag : Int) -> UITextField? {
return self.view.viewWithTag(tag + 1) as? UITextField
}
func getPreviousResponderFor(tag : Int) -> UITextField? {
return self.view.viewWithTag(tag - 1) as? UITextField
}
Run Code Online (Sandbox Code Playgroud)
您需要按顺序提供 textFields 标签,您希望下一个/上一个按钮响应。