我如何通过iPhone键盘上的“下一步”按钮浏览所有的文本字段?

最后一个文本字段应该关闭键盘。

我已经设置了IB按钮(下一步/完成),但现在我卡住了。

我实现了textFieldShouldReturn动作,但现在下一步和完成按钮关闭键盘。


当前回答

一个快速扩展,应用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)
    }
}

它很容易使用:

UITextField.connectFields([field1, field2, field3])

扩展将设置返回按钮为“下一步”为所有但最后一个字段和“完成”为最后一个字段,并转移焦点/解散键盘时,这些被轻敲。

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

斯威夫特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)
        }
    }

其他回答

如果有人想这样。我认为这是最接近问题所要求的要求

下面是我如何实现它

为需要设置的每个文本字段添加附件视图,使用

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
}

使用以下函数来处理轻拍

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
}

您需要按您希望下一个/前一按钮响应的顺序给出textFields标记。

没有usings标签,也没有为nextField/nextTextField添加属性,你可以尝试模拟TAB,其中"testInput"是你当前的活动字段:

if ([textInput isFirstResponder])
    [textInput.superview.subviews enumerateObjectsAtIndexes:
     [NSIndexSet indexSetWithIndexesInRange:
      NSMakeRange([textInput.superview.subviews indexOfObject:textInput]+1,
                  [textInput.superview.subviews count]-[textInput.superview.subviews indexOfObject:textInput]-1)]
                                                    options:0 usingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
                                                        *stop = !obj.hidden && [obj becomeFirstResponder];
                                                    }];
if ([textInput isFirstResponder])
    [textInput.superview.subviews enumerateObjectsAtIndexes:
     [NSIndexSet indexSetWithIndexesInRange:
      NSMakeRange(0,
                  [textInput.superview.subviews indexOfObject:textInput])]
                                                    options:0 usingBlock:^(UIView *obj, NSUInteger idx, BOOL *stop) {
                                                        *stop = !obj.hidden && [obj becomeFirstResponder];
                                                    }];

这是我对这个问题的解决方案。

为了解决这个问题(因为我讨厌依赖标签来做事情),我决定向UITextField对象添加一个自定义属性。换句话说,我在UITextField上创建了一个这样的类别:

UITextField + Extended.h

@interface UITextField (Extended)

@property(retain, nonatomic)UITextField* nextTextField;

@end

UITextField +扩展。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

下面是我如何使用它:

UITextField *textField1 = ...init your textfield
UITextField *textField2 = ...init your textfield
UITextField *textField3 = ...init your textfield

textField1.nextTextField = textField2;
textField2.nextTextField = textField3;
textField3.nextTextField = nil;

实现textFieldShouldReturn方法:

- (BOOL)textFieldShouldReturn:(UITextField *)theTextField {

    UITextField *next = theTextField.nextTextField;
    if (next) {
        [next becomeFirstResponder];
    } else {
        [theTextField resignFirstResponder];
    }

    return NO; 
}

我现在有一个UITextField的链表,每一个都知道下一个是谁。

希望能有所帮助。

我尝试使用一种更复杂的方法来解决这个问题,该方法基于为UITableView中的每个单元格(或UITextField)分配一个稍后可以检索的唯一标签值: activate-next-uitextfield-in-uitableview-ios

我希望这能有所帮助!

 -(BOOL)textFieldShouldReturn:(UITextField *)textField
{
   [[self.view viewWithTag:textField.tag+1] becomeFirstResponder];
   return YES;
}