Using NSMutableAttributedString
to color my strings in UITextField
, but then user cannot cut, copy, or delete the strings. For example, using the code below, if I type "blue red @green" then try to just delete out blue or cut out blue, when I try the cursor moves to the last letter in the UITextfield
?
Any suggestions?
- (void)colorText {
NSMutableAttributedString * string = [[NSMutableAttributedString alloc]initWithString:self.thing.text];
NSArray *words=[self.thing.text componentsSeparatedByString:@" "];
for (NSString *word in words) {
if([word isEqualToString:@""]) {continue;};
if ([word hasPrefix:@"@"]) {
NSRange range=[self.thing.text rangeOfString:word];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor greenColor] range:range];
} else {
NSRange range=[self.thing.text rangeOfString:word];
[string addAttribute:NSForegroundColorAttributeName value:[UIColor darkGrayColor] range:range];
}
}
[self.thing setAttributedText:string];
}
The problem is that you're setting the text of the string each time, which wipes the current string and puts in a new one, which moves your cursor to the end and overrides any edits you were going to make to the original string. You could make the edits yourself, call colorText
and then return NO
, which will make your edits but you'll still have the cursor problem.
The solution is to get the range of the cursor, make the edits manually, call colorText
, put the cursor back to where it should be, and then return NO
. I know it sounds convoluted, but the code isn't too bad.
- (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];
[textField colorText]; // or however you call this on your field
// 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;
}