YYText
YYText copied to clipboard
使用百度或者搜狗英文输入联想问题
有些英文字符选择联想的词汇后直接添加在最后 不是替换原来的 调试的时候发现 输入“sdk” 没有进入- (void)setSelectedTextRange:(YYTextRange *)selectedTextRange;
这些方法都是由系统调用的,YYTextView 里无法控制。 目前调试时发现确实是有问题,暂时还没找到解决办法。。。 稍后我会继续跟进一下看看。
我也遇到类似问题,请问版主这个问题解决了么?
期待版主早日解决这个问题
我做过键盘开发,正常情况下,第三方键盘是不能像系统一样控制 selection 的,所以要做这种联想更正的话,只能把旧的删除,然后再重新输入。百度搜狗不知道用了什么黑科技去实现的这个特性,目前看不是删除再输入,猜测有可能是调用了某些私有方法。
我试着断点看了一下。使用搜狗输入法和UITextView,在上图所说的情况下,当点击联想得到的字符串时,
-[UIKeyboardImpl performKeyboardOutput:]
在这个方法断点输出参数的时候,得到的输出是
(lldb) po $x2
<_UIInputViewKeyboardOutput: 0x15e203340; delete 9; insert jccccffff>
输出里面有一个delete 9
那个参数output里面有两个有意义的值
output.deletionCount = 9
output.insertionText = "jccccffff"
然后在里面断点的时候发现,UIKeyboardImpl
针对这个delete 9
向UITextView
调用了9
次的_deleteBackwardAndNotify:
方法,而UITextView则调用了-[UITextInputController _performWhileSuppressingDelegateNotifications:]
方法,从名字可以看到,没有去触发任何delegate回调。
在删除这些字符之后才调用了insertText:
方法插入所选择的联想得到的字符串。
但是在使用YYTextView的时候就没有这些过程,在
-[UIKeyboardImpl performKeyboardOutput:]
这里断点的时候参数output里面的deletionCount有时有有时没有,也没有搞懂它的规律是什么。
我在YYTextView里面实现了一下_deleteBackwardAndNotify:
方法,和上面的output参数一致,只是偶尔会调用。不过_deleteBackwardAndNotify:
好像是UITextInput_Internal
这个私有协议的方法。
找到一个自定义的text view
FastTextView
这个text view
是不存在这个问题的。系统会去调用它的deleteBackward
方法。
问题可能是出在对
- (void)selectionWillChange:(nullable id <UITextInput>)textInput;
- (void)selectionDidChange:(nullable id <UITextInput>)textInput;
这两个方法的调用上。
在系统的UITextView
上好像只有在
- (void)setMarkedText:(nullable NSString *)markedText selectedRange:(NSRange)selectedRange;
- (void)unmarkText;
这两个方法内部还有点击选择等操作的时候会调用。
- (void)_replaceRange:(YYTextRange *)range withText:(NSString *)text notifyToDelegate:(BOOL)notify
我把YYTextView
这个方法里面的selectionDidChange
调用都删掉之后就没有这个问题了。
但是不知道会不会对其他部分的代码造成影响。
(把两个的调用都删掉反而不行,这里还是想不通为什么,或许跟其他地方的调用有关?)
@ibireme 不知道对解决这个问题有没有帮助。。
感谢提供信息,稍微调试了下,感觉可能与这几对方法的调用时机有关。。明天再看一下。
仔细调整了一下 inputDelegate 的几个调用方法的顺序和调用时机,还是多少有些问题。。
@ibireme 这样问题解决了吗
联想/换行/空格 问题默默求解决。。。@ibireme
解决了么? iphone5s, iOS10.0.1, 使用第三方输入法还是会出现上述问题. 同时系统键盘还是会出现输入中间有空格的问题("sc" , 联想"school" 出现"sc hool"). @ibireme
使用系統預設語音輸入文字也有類似情況
按楼上的方法把YYTextView里面的selectionDidChange调用都删掉 同时删除- (void)_replaceRange:(YYTextRange *)range withText:(NSString *)text notifyToDelegate:(BOOL)notify方法的_selectedTextRange = [self _correctedTextRange:_selectedTextRange]; 暂时可以了。 _selectedTextRange在计算newRange的时候变化了,_innerText还是原来的内容,调用_correctedTextRange方法不合适。
@ibireme 翻了一下文档,苹果的《Text Programming Guide for iOS》里面有提到下面几个方法的调用时机。
- (void)selectionWillChange:(nullable id <UITextInput>)textInput;
- (void)selectionDidChange:(nullable id <UITextInput>)textInput;
- (void)textWillChange:(nullable id <UITextInput>)textInput;
- (void)textDidChange:(nullable id <UITextInput>)textInput;
Text Programming Guide for iOS > Lower Level Text-Handling Technologies > Communicating with the Text Input System > Overview of the Client Side of Text Input > Tasks of a UITextInput Object
的最后一段文字:
When changes occur in the text view due to external reasons—that is, they aren't caused by calls from the text input system—the UITextInput object should send textWillChange:, textDidChange:, selectionWillChange:, and selectionDidChange: messages to the input delegate (which it holds a reference to). For example, when users tap a text view and you set the range of selected text to place the insertion point under the finger, you would send selectionWillChange: before you change the selected range, and you send selectionDidChange: after you change the range.
这份文档里面也有其他相关方法的说明和一个实现。
苹果说的除了 text input system 的意思,应该是把键盘也除外了吧。
在Communicating with the Text Input System
第一句话就说:
The text input system of iOS manages the keyboard.
上面所说的把某个方法删掉就没有问题了应该就是这个原因吧,因为现在 https://github.com/ibireme/YYText/commit/02eba9ffd392892a2fca5ed98f6628d29003ef78 代码里面有很多调用- (void)replaceRange:(YYTextRange *)range withText:(NSString *)text
的地方,比如deleteBackward
那几个方法就可能会由键盘来触发。
而且感觉selection
的改动应该比text
要靠后吧,在- (YYTextRange *)_correctedTextRange:(YYTextRange *)range
里面有对- (BOOL)_isTextRangeValid:(YYTextRange *)range
的调用,如果这个时候text
还没有改的话,那_isTextRangeValid
的调用就有问题了吧。
@sablib 首先感谢 #691 提供的解决方案,在iOS13之前解决了三方输入法和系统英文联想的问题。但iOS13系统上,出现了两个问题: 1:系统的输入法出现了双光标的问题。(输入中文,然后接着输入数字或者标点符号会出现双光标) 2:百度输入法点击联想单词,光标位置留在了单词的前面。 我尝试了切回原作者 @ibireme 的代码,可以解决问题1,但是问题2并不能解决。不知道大神还有没有继续跟进这个问题?
@Auk513 我最近没有在做 iOS 开发了,后续也没有再关注这个问题。
我已经四年不做了…------------------ 原始邮件 ------------------ @.> 发送时间: 2021年4月19日(星期一) 晚上8:01 @.>; 抄送: "Yufeng @.@.>; 主题: Re: [ibireme/YYText] 使用百度或者搜狗英文输入联想问题 (#89)
https://github.com/ibireme/YYText/pull/965/commits/6e6841d1db9174dbbdc7918ab08b50fa7a83f381 我调试后发现其实是selectedRange不对造成的 另外selectionWillChange和textwillchange的调用感觉有异样,导致更新_innerText前切去干别的事情了 出于这个判断,改了这些东西在_replaXXX的执行时机,这样改好像可以解决,大家快来一起试试