为了作特殊字符输入,作了获取和设置光标位置的功能,经过selectedTextRange属性来实现的,在iOS11上测试,一切没问题,代码以下c++
- (void)setCursorPosition:(int)position { NSRange range = NSMakeRange(position, 0); [self setSelectedRange:range]; } - (int)getCursorPosition { NSRange range = [self selectedRange]; NSUInteger position = range.location + range.length; return (int)position; } - (NSRange) selectedRange { UITextPosition* beginning = self.beginningOfDocument; UITextRange* selectedRange = self.selectedTextRange; UITextPosition* selectionStart = selectedRange.start; UITextPosition* selectionEnd = selectedRange.end; NSInteger location = [self offsetFromPosition:beginning toPosition:selectionStart]; NSInteger length = [self offsetFromPosition:selectionStart toPosition:selectionEnd]; return NSMakeRange(location, length); } - (void) setSelectedRange:(NSRange) range { UITextPosition* beginning = self.beginningOfDocument; UITextPosition* startPosition = [self positionFromPosition:beginning offset:range.location]; UITextPosition* endPosition = [self positionFromPosition:beginning offset:range.location + range.length]; UITextRange* selectionRange = [self textRangeFromPosition:startPosition toPosition:endPosition]; [self setSelectedTextRange:selectionRange]; } - (void)setText:(NSString *)text { if (![text isEqualToString:self.text]) { UITextRange *selection = self.selectedTextRange; NSInteger oldTextLength = self.text.length; [super setText:text]; if (selection.empty) { // maintain cursor position relative to the end of the old text NSInteger start = [self offsetFromPosition:self.beginningOfDocument toPosition:selection.start]; NSInteger offsetFromEnd = oldTextLength - start; NSInteger newOffset = text.length - offsetFromEnd; UITextPosition *position = [self positionFromPosition:self.beginningOfDocument offset:newOffset]; [self setSelectedTextRange:[self textRangeFromPosition:position toPosition:position]]; } } }
后来发如今IOS9和iOS8上面获取/设置光标位置都有问题,具体表现为:objective-c
当输入框处于激活状态的时候,能够正常获取/设置,可是键盘消失的时候,无论怎么设置,selectedTextRange返回的一直是nil,致使光标位置一直为0。测试
这个问题描述看起来很简单清晰,但我倒是通过一轮轮排查才总结出来,由于刚开始直观的怀疑是lua中sdk业务和c++包装的逻辑里面有鬼致使, 这也是个血的教训,之后再遇到相似问题,必定要先写个简单Demo进行尝试。lua
刚开始怀疑是上层业务逻辑代码有鬼,因此在原生打断点观察不一样系统下的执行状况,而后真的发现了区别:日志
iOS11:键盘消失的时候,什么也没发生;code
iOS9/iOS8: 键盘消失的时候,会执行setText方法,一顿调查后,发现是iOS系统的处理,调用栈以下:内存
frame #0: 0x000d7ac8 UITest`-[XYTextField setText:](self=0x1659e200, _cmd="setText:", text=0x165d91b0) at XYTextField.m:60 frame #1: 0x2685ea9a UIKit`-[UITextField _endedEditing] + 170 frame #2: 0x2685e918 UIKit`-[UITextField willDetachFieldEditor:] + 128 frame #3: 0x2674172c UIKit`-[UIFieldEditor becomeFieldEditorForView:] + 320 frame #4: 0x2685e6c0 UIKit`-[UITextField _resignFirstResponder] + 228 frame #5: 0x26835ff8 UIKit`-[UIResponder _finishResignFirstResponder] + 260 frame #6: 0x27035532 UIKit`-[UITextField _finishResignFirstResponder] + 42 frame #7: 0x267d731a UIKit`-[UIResponder resignFirstResponder] + 278 frame #8: 0x2685e424 UIKit`-[UITextField resignFirstResponder] + 128
到此,直观判断,是因为低版本系统多了一步setText致使光标位置失效;再次,因为个人粗心,继续怀疑到这个setText是由业务层引发的,而后作了各类排查和无谓的斗争….文档
最后,才决定写个简单Demo进行验证,才最终肯定setText是系统行为引发,而且在setText内部实现先后打印日志,发现执行先后的光标位置都是0,证实和setText没有关系,对个人直观判断进行了啪啪打脸~get
既然和setText无关,那就只能是和输入框的状态有关了,为了证实,我监听了下面两个回调:cmd
- (BOOL)textFieldShouldEndEditing:(UITextField *)textField { NSLog(@"CursorPosition:%d", [_textField getCursorPosition]); return YES; } - (void)textFieldDidEndEditing:(UITextField *)textField { NSLog(@"CursorPosition:%d", [_textField getCursorPosition]); }
在should的回调中输出正确,在did中输出为0,至此我才有了最终的结论:
低版本系统上,输入框非激活状态下,selectedTextRange无效。简单实验,发现确实如此。
在苹果文档没有看到相关介绍,网上也没有找到方案,最终决定放弃实时获取光标位置,换成内存记录的方式:
在textFieldShouldEndEditing或者输入内容变化的时候(根据具体需求)获取光标位置并进行记录,供后续特殊字符的输入使用。
本次解决问题虽然时间不是特别长(半天时间),可是整个过程能够说很是的业余和不专业; 虽然工做遇到的各类问题愈来愈多,可是基础分析解决问题的能力,仍是要注意的。
自我安慰,这种状况跟如今工做涉及技术类型比较杂,业务复杂度高有关系。 之后的工做中,注意方式方法,多总结吧~