問(wèn)題說(shuō)明
今天使用UITextfield需要右對(duì)齊輸入,但是當(dāng)設(shè)置右對(duì)齊第一個(gè)字符輸入空格后,神奇的一幕發(fā)生了瓶蚂,如下圖,如果第一個(gè)字符輸入的是空格宣吱,那么光標(biāo)會(huì)跳到左側(cè)窃这;如果輸入其它字符,然后輸入空格凌节,此時(shí)輸入的空格不會(huì)立即顯示钦听,直到再次輸入其它字符時(shí)該空格會(huì)與輸入的字符同時(shí)顯示出來(lái)
。

解決思路
解決思路很簡(jiǎn)單倍奢,就是將我們輸入的普通空格使用Non-breaking space代替。
解決方案
方案1:通過(guò)代理方法監(jiān)聽(tīng)textfield的輸入垒棋。
1.首先設(shè)置控制器作為textfield的代理卒煞,
self.textField.delegate = self;
2.監(jiān)聽(tīng)文本的輸入,做如下處理
- (BOOL)textField:(UITextField *)textField
shouldChangeCharactersInRange:(NSRange)range
replacementString:(NSString *)string
{
/* 如果不是右對(duì)齊叼架,直接返回YES畔裕,不做處理 */
if (textField.textAlignment != NSTextAlignmentRight) {
return YES;
}
/* 在右對(duì)齊的情況下*/
// 如果string是@""衣撬,說(shuō)明是刪除字符(剪切刪除操作),則直接返回YES扮饶,不做處理
// 如果把這段刪除具练,在刪除字符時(shí)光標(biāo)位置會(huì)出現(xiàn)錯(cuò)誤
if ([string isEqualToString:@""]) {
return YES;
}
/* 在輸入單個(gè)字符或者粘貼內(nèi)容時(shí)做如下處理,已確定光標(biāo)應(yīng)該停留的正確位置甜无,
沒(méi)有下段從字符中間插入或者粘貼光標(biāo)位置會(huì)出錯(cuò) */
// 首先使用 non-breaking space 代替默認(rèn)輸入的@“ ”空格
string = [string stringByReplacingOccurrencesOfString:@" "
withString:@"\u00a0"];
textField.text = [textField.text stringByReplacingCharactersInRange:range
withString:string];
//確定輸入或者粘貼字符后光標(biāo)位置
UITextPosition *beginning = textField.beginningOfDocument;
UITextPosition *cursorLoc = [textField positionFromPosition:beginning
offset:range.location+string.length];
// 選中文本起使位置和結(jié)束為止設(shè)置同一位置
UITextRange *textRange = [textField textRangeFromPosition:cursorLoc
toPosition:cursorLoc];
// 選中字符范圍(由于textRange范圍的起始結(jié)束位置一樣所以并沒(méi)有選中字符)
[textField setSelectedTextRange:textRange];
return NO;
}
3.如果需要拿到textfield中的text使用扛点,在使用前記得將 non-breaking space替換回來(lái)
[self.textField.text stringByReplacingOccurrencesOfString:@"\u00a0"
withString:@" "];
弊端分析:上面代理方法textField: shouldChangeCharactersInRange: replacementString:
對(duì)于很多輸入字符返回的是NO,因此不能很好的監(jiān)聽(tīng)UITextFieldTextDidChangeNotification
岂丘,因此不推薦使用陵究。
效果演示

方案2:通過(guò)addTarget: action: forControlEvents: 給textField添加響應(yīng)事件
在此,自定義了一個(gè)textField奥帘,code如下:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// 給textfield添加響應(yīng)事件
[self addTarget:self
action:@selector(replaceNormalSpaceUsingNonbreakingSpace)
forControlEvents:UIControlEventEditingChanged];
}
return self;
}
// 在響應(yīng)事件中將@" "替換為non-breaking space
- (void)replaceNormalSpaceUsingNonbreakingSpace
{
UITextRange *textRange = self.selectedTextRange;
self.text = [self.text stringByReplacingOccurrencesOfString:@" "
withString:@"\u00a0"];
[self setSelectedTextRange:textRange];
}
說(shuō)明:如果需要拿到textfield中的text使用铜邮,同樣需要將 non-breaking space替換回來(lái)。
該方法可以有效的解決問(wèn)題寨蹋,還能監(jiān)聽(tīng)UITextFieldTextDidChangeNotification
松蒜,推薦使用。
效果演示

仍存在的問(wèn)題
當(dāng)我們最后輸入的是空格的時(shí)候已旧,那么當(dāng)textfield不是第一響應(yīng)者的時(shí)候牍鞠,那么最后的空格依然不可見(jiàn)。如下所示:

解決思路:可以在textfield右側(cè)放一個(gè)view评姨,當(dāng)輸入結(jié)束時(shí)难述,計(jì)算輸入內(nèi)容最后面空格的寬度,然后作為view的寬度吐句,當(dāng)textfield成為第一響應(yīng)者時(shí)胁后,令view的寬度為0。
PS:誰(shuí)有更好的方法@一下哦嗦枢。
參考
基本是下面解決方案的匯總攀芯,下面有的回答也存在一些其他小問(wèn)題。
clickme