33

任何人都可以帮我解决这个问题:我需要实现UITextField输入数字。此数字应始终为十进制格式,有 4 位,例如 12.3456 或 12.3400。所以我创建NSNumberFormatter了一个帮助我处理小数位的东西。

我将UITextField值设置为

-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 方法。我处理输入,使用格式化程序,最后调用[textField setText: myFormattedValue];

这工作正常,但这个调用也将光标移动到我的字段的末尾。这是不想要的。例如,我的字段中有 12.3400,光标位于开头,用户键入数字 1。结果值为 112.3400,但光标在末尾移动。我想在用户期望时以光标结束(就在最近添加的数字 1 之后)。有一些关于设置光标的主题,TextView但这是UITextField. 我还尝试捕获selectedTextRange该字段,它可以正确保存光标位置,但在setText方法调用之后,它会自动更改并且原点UITextRange丢失(更改为当前)。希望我的解释很清楚。

请在这件事上给予我帮助。非常感谢您。

编辑:最后,我决定在整个编辑后将功能切换为更改格式,并且效果很好。我通过添加一个选择器来完成它forControlEvents:UIControlEventEditingDidEnd

4

6 回答 6

41

更改属性后,在设置 text 属性后UITextField.text,任何先前对旧文本的引用UITextPositionUITextRange与旧文本关联的对象都将设置为 nil。您需要在设置 text 属性之前存储操作后的文本偏移量。

这对我有用(注意,如果在下面的示例中从 t 中删除任何字符,则必须测试 cursorOffset 是否为 < textField.text.length):

- (BOOL) textField:(UITextField *) textField shouldChangeCharactersInRange:(NSRange) range replacementString:(NSString *) string

{
    UITextPosition *beginning = textField.beginningOfDocument;
    UITextPosition *start = [textField positionFromPosition:beginning offset:range.location];
    UITextPosition *end = [textField positionFromPosition:start offset:range.length];
    UITextRange *textRange = [textField textRangeFromPosition:start toPosition:end];

    // this will be the new cursor location after insert/paste/typing
    NSInteger cursorOffset = [textField offsetFromPosition:beginning toPosition:start] + string.length; 

    // now apply the text changes that were typed or pasted in to the text field
    [textField replaceRange:textRange withText:string];

    // now go modify the text in interesting ways doing our post processing of what was typed...
    NSMutableString *t = [textField.text mutableCopy];
    t = [t upperCaseString];
    // ... etc

    // now update the text field and reposition the cursor afterwards
    textField.text = t;
    UITextPosition *newCursorPosition = [textField positionFromPosition:textField.beginningOfDocument offset:cursorOffset];
    UITextRange *newSelectedRange = [textField textRangeFromPosition:newCursorPosition toPosition:newCursorPosition];
    [textField setSelectedTextRange:newSelectedRange];

    return NO;
}
于 2013-02-09T23:37:09.353 回答
5

这是快速版本:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
    let beginning = textField.beginningOfDocument
    let start = textField.positionFromPosition(beginning, offset:range.location)
    let end = textField.positionFromPosition(start!, offset:range.length)
    let textRange = textField.textRangeFromPosition(start!, toPosition:end!)
    let cursorOffset = textField.offsetFromPosition(beginning, toPosition:start!) + string.characters.count

// just used same text, use whatever you want :)
    textField.text = (textField.text! as NSString).stringByReplacingCharactersInRange(range, withString: string)

    let newCursorPosition = textField.positionFromPosition(textField.beginningOfDocument, offset:cursorOffset)
    let newSelectedRange = textField.textRangeFromPosition(newCursorPosition!, toPosition:newCursorPosition!)
    textField.selectedTextRange = newSelectedRange

    return false
}
于 2015-11-25T15:44:54.927 回答
4

这是一个 swift 3 版本

extension UITextField {
    func setCursor(position: Int) {
        let position = self.position(from: beginningOfDocument, offset: position)!
        selectedTextRange = textRange(from: position, to: position)
    }
}
于 2016-12-07T17:12:44.250 回答
4

实际上对我有用的东西非常简单,只使用了 dispatch main async:

DispatchQueue.main.async(execute: {
  textField.selectedTextRange = textField.textRange(from: start, to: end)
})
于 2017-10-23T13:41:42.010 回答
2

实现此答案中描述的代码:将光标移动到 UITextField 的开头

NSRange beginningRange = NSMakeRange(0, 0);
NSRange currentRange = [textField selectedRange];
if(!NSEqualRanges(beginningRange, currentRange))
{
    [textField setSelectedRange:beginningRange];
}

编辑:这个答案看来,如果您使用的是 iOS 5 或更高版本,您似乎可以将此代码与您的 UITextField 一起使用。否则,您需要改用 UITextView。

于 2012-06-22T14:54:09.163 回答
0

Swift X. 防止光标从最后一个位置移动。

func textFieldDidChangeSelection(_ textField: UITextField) {
    let point = CGPoint(x: bounds.maxX, y: bounds.height / 2)
    if let textPosition = textField.closestPosition(to: point) {
        textField.selectedTextRange = textField.textRange(from: textPosition, to: textPosition)
    }
}
于 2019-10-10T11:44:45.280 回答