自定义iOS键盘扩展中如何可靠获取完整选中文本?
我太懂这种被iOS键盘扩展文本限制拿捏的痛苦了!你说的textDocumentProxy.selectedText只返回前后片段、移动光标也捞不到完整内容的问题,我之前做键盘扩展的时候也踩过一模一样的坑。下面是我亲测有效的几个解决办法,帮你搞定这个麻烦:
第一步:先把「完全访问权限」拉满
这是最关键的前提!很多人忽略了这个设置:你得在键盘扩展的Info.plist里把RequestsOpenAccess设为YES,然后引导用户在系统设置的「键盘」选项里开启你的键盘的完全访问权限。没有这个权限的话,系统会严格限制你能获取的文本内容,selectedText截断就是典型的权限受限表现。另外还要注意,有些特殊输入框(比如密码框、系统受限文本域)本身就不让访问完整文本,这种情况要提前做判断,别白费力气。组合
textDocumentProxy的API拼接完整内容
当权限开到位后,别光盯着selectedText,试试结合selectedRange、documentContextBeforeInput和documentContextAfterInput来推导:- 先拿到当前的选中范围:
let selectedRange = textDocumentProxy.selectedRange,这里的location是选中起始位置,length是选中长度。 - 用
documentContextBeforeInput获取选中起始位置之前的全部文本(权限开启后这个内容会完整很多),再通过adjustTextPositionByCharacterOffset(selectedRange.length)把光标移到选中结束的位置,此时再获取documentContextBeforeInput,两者的差值就是完整的选中文本。 - 要是还是有截断,就多试几次小步移动光标,每次获取一段文本片段,最后拼接起来——虽然麻烦,但对付长文本选中的情况很管用。
- 先拿到当前的选中范围:
监听文本变化通知,实时缓存文本状态
你可以注册UITextInputCurrentInputModeDidChangeNotification,或者监听textDocumentProxy的textDidChangeNotification,在用户选中文本的瞬间就捕获完整的文本内容。不过要记得维护一个本地的文本缓存,确保缓存内容和输入框的实时内容同步,避免拼接出错。特殊场景的兜底处理
要是碰到某些顽固的输入框,哪怕开了权限也拿不到完整文本,那只能做兜底:给用户一个提示,比如「当前输入框无法获取完整选中文本,请尝试复制后粘贴到支持的输入框」,别让用户一脸懵。
备注:内容来源于stack exchange,提问作者amirhozaifa

