格式的UITextField文本,而无需将光标移动到结束

问题描述:

我想处理一个新的文本输入,按键通过按键后NSAttributedString样式应用到的UITextField。问题是,无论何时我替换文本,光标都会在每次更改时跳到最后。这是我目前的做法...格式的UITextField文本,而无需将光标移动到结束

接收和显示文本更改立即(同样的问题适用于当我返回false和做手工的文本替换)

func textField(textField: UITextField!, shouldChangeCharactersInRange range: NSRange, replacementString string: String!) -> Bool {   
    let range:NSRange = NSRange(location: range.location, length: range.length) 
    let newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string); 
    return true 
} 

我订阅了UITextFieldTextDidChangeNotification通知。这触发了造型。当文本发生变化时,我使用某种格式()函数将其替换为格式化版本(NSAttributedString)(NSString)。

func textFieldTextDidChangeNotification(userInfo:NSDictionary) { 
    var attributedString:NSMutableAttributedString = NSMutableAttributedString(string: fullString) 
    attributedString = format(textField.text) as NSMutableAttributedString 
    textField.attributedText = attributedString 
} 

造型工作正常。但是,在每次文本替换之后,光标跳转到字符串的末尾。如何关闭此行为或手动将光标移回到开始编辑的位置? ...还是有更好的解决方案来编辑​​文本的样式吗?

使其工作的方法是获取光标位置,更新字段内容,然后将光标替换为其原始位置。我不确定在Swift中的确切等价物,但以下是我如何在Obj-C中完成的。

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string 
{ 
    UITextPosition *beginning = textField.beginningOfDocument; 
    UITextPosition *cursorLocation = [textField positionFromPosition:beginning offset:(range.location + string.length)]; 

    textField.text = [textField.text stringByReplacingCharactersInRange:range withString:string]; 

    /* MAKE YOUR CHANGES TO THE FIELD CONTENTS AS NEEDED HERE */ 

    // cursorLocation will be (null) if you're inputting text at the end of the string 
    // if already at the end, no need to change location as it will default to end anyway 
    if(cursorLocation) 
    { 
     // set start/end location to same spot so that nothing is highlighted 
     [textField setSelectedTextRange:[textField textRangeFromPosition:cursorLocation toPosition:cursorLocation]]; 
    } 

    return NO; 
} 
+0

哦,完美。它就是这样的。谢谢 – Bernd 2014-10-09 18:17:04

这是一个老问题,但我也有类似的问题,有以下斯威夫特解决它:

// store the current cursor position as a range 
var preAttributedRange: NSRange = textField.selectedRange 
// apply attributed string 
var attributedString:NSMutableAttributedString = NSMutableAttributedString(string: fullString) 
attributedString = format(textField.text) as NSMutableAttributedString 
textField.attributedText = attributedString 
// reapply the range 
textField.selectedRange = preAttributedRange 

它工作在我的应用程序的情况下,希望它是有用的人!

+0

这有用奇迹,非常感谢,因为上面的标记解决方案在某些情况下不适用于我。 – jpincheira 2016-09-06 14:33:23

这是一个适用于swift 2的代码。享受它!

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 
    let beginnig: UITextPosition = textField.beginningOfDocument 

    if let txt = textField.text { 
     textField.text = NSString(string: txt).stringByReplacingCharactersInRange(range, withString: string) 
    } 

    if let cursorLocation: UITextPosition = textField.positionFromPosition(beginnig, offset: (range.location + string.characters.count)) { 
     textField.selectedTextRange = textField.textRangeFromPosition(cursorLocation, toPosition: cursorLocation) 
    } 

    return false 
} 

请注意,最后“如果让”应该始终停留在代码的末尾。

+0

'UITextPosition * cursorLocation = [textField positionFromPosition:starting offset:(range.location + string.length)];'不再需要? – Daniel 2016-02-08 16:13:22

感谢@ Stonz2的Objective-C中的代码。它像一个魅力!我在我的Swift项目中使用它。 Swift中的代码相同:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { 

    let positionOriginal = textField.beginningOfDocument 
    let cursorLocation = textField.positionFromPosition(positionOriginal, offset: (range.location + NSString(string: string).length)) 

    /* MAKE YOUR CHANGES TO THE FIELD CONTENTS AS NEEDED HERE */ 

    if(cursorLocation != nil) { 
     textField.selectedTextRange = textField.textRangeFromPosition(cursorLocation!, toPosition: cursorLocation!) 
    } 
    return false 
} 
+1

在我的情况下,我需要textView中的这段代码:ShouldChangeTextInRange,我只替换了“textField” - >“textView”和“string” - >“text”,它开箱即用。谢谢! – Vitalii 2016-10-10 11:30:44