2014-10-09 15 views
18

I NSAttributedString Stile einen UITextField nach der Verarbeitung einen neuen Texteingabe Tastendruck per Tastendruck anzuwenden versuchen. Das Problem ist, dass der Cursor jedes Mal, wenn ich den Text ersetze, bei jeder Änderung das letzte Mal springt. Hier ist meine aktuelle Ansatz ...Format UITextField Text ohne Cursor-Bewegung des mit dem Ende

empfangen und anzeigen Text Änderung sofort (gleiche Problem gilt, wenn ich falsch zurückkehren und tun das Ersetzen von Text manuell)

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 
} 

ich zum UITextFieldTextDidChangeNotification Benachrichtigung abonniert. Dies löst das Styling aus. Wenn der Text geändert wird, ersetze ich es (NSString) mit der formatierten Version (NSAttributedString) mithilfe einiger Format() -Funktion.

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

Styling funktioniert gut so. Nach jedem Textersatz springt der Cursor jedoch an das Ende der Zeichenfolge. Wie kann ich dieses Verhalten ausschalten oder den Cursor manuell dorthin zurückbewegen, wo die Bearbeitung begonnen hat? ... oder gibt es eine bessere Lösung, um den Text während der Bearbeitung zu formatieren?

Antwort

31

Der Weg, um dies zu erledigen, ist die Position des Cursors zu greifen, den Inhalt des Feldes zu aktualisieren und dann den Cursor an seine ursprüngliche Position zu setzen. Ich bin mir nicht sicher, welches Äquivalent Swift genau hat, aber das Folgende ist, wie ich es in Obj-C machen würde.

- (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

Oh, perfekt. Es funktioniert so. Danke – Bernd

8

Dies ist eine alte Frage, aber ich hatte ein ähnliches Problem und gelöst wird sie mit folgendem Swift:

// 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 

Es ist im Rahmen meiner App funktioniert, hoffentlich ist es für jemanden nützlich!

+0

das funktioniert Wunder, vielen Dank, weil die markierte Lösung oben für mich in einigen Fällen nicht funktionierte. – jpincheira

2

Dies ist ein Code, der für swift 2 funktioniert. Viel Spaß!

Beachten Sie, dass das letzte "wenn lassen" immer am Ende des Codes bleiben sollte.

+0

Ist 'UITextPosition * cursorLocation = [TextField positionFromPosition: Anfang Offset: (range.location + string.length)];' Wird nicht mehr benötigt? – Daniel

7

Danke @ Stonz2 durch den Code in Objective-C. Es wirkt wie ein Zauber! Ich habe es in meinem Swift-Projekt verwendet. Der gleiche Code in 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

In meinem Fall brauchte ich diesen Code in textView: ShouldChangeTextInRange, ich habe nur "textField" -> "textView" und "string" -> "text" ersetzt und es funktionierte aus der Box. Vielen Dank! – Vitalii

Verwandte Themen