我一直在为 iOS 7 重新编写我的应用程序。它现在使用新的 TextKit API。我几乎完成了,但自从我开始进行过渡以来,还有一个问题一直让我头疼。
问题:当我在 UITextView 中输入文本时,有时视图会向上滚动隐藏光标。很难确定模式,但它似乎发生在我删除一行并且下面的文本必须向上移动之后。但只有第二次我删除了一行,并且只删除了文档中的某些行(通常只有换行符但并不总是......)
我曾尝试在 stackoverflow 上使用这些解决方案:
UITextView 在每插入一个新行后都会滚动,所以这些行是不可见的(iPhone OS)
在 iOS 7 中滚动到 UITextView 不稳定的底部
当 UITextView 中有 UITableView 时,还有许多其他问题导致滚动无法正常工作。我的视图中没有表视图。
我想指出,我已经继承了 UITextView 并发现它肯定是 iOS 7 调用不仅向上滚动视图。此外,更奇怪的是,当您按下后退按钮(从 UITextView 中删除一个字符)时,它会向textViewDidChangeSelection:
. 这是发生问题时的调用堆栈。(当问题没有发生时,我仍然会接到两次委托委托textViewDidChangeSelection:
……这似乎是正常的):
- UITextView 委托
textViewDidChangeSelection:
包含要删除的字符的位置,长度为 1。(即 1050,1) - 再次调用UITextView 委托
textViewDidChangeSelection:
并包含相同的位置但长度为零。(即 1050,0) - scrollViewDidScroll(最多 3 次。但一般只有一次)
- 然后 iOS 7 调用
UITextView.scrollRangeToVisible:
FIRST 调用的范围为 {1050,1}。这对我来说毫无意义。我知道这是在内部调用的,而不是从我的任何代码中调用的,因为调用此内部 API时没有_ensureselectionvisible
任何回溯到我可能用来调用滚动事件的函数。
大概前两个调用只是选择字符,然后在内部调用 deleteBackwards。这就说得通了。不过在那之后我就瞎了。我不知道它为什么会滚动或为什么会调用scrollRangeToVisible:
错误的范围。
我已经能够通过在用户编辑文本时UITextView.scrollRangeToVisible:
返回 w/o call来覆盖来缓解这个问题。[super scrollRangeToVisible]
我通过覆盖一些滚动视图委托调用并设置一个表示不能滚动的标志来做到这一点。对我来说,这是一个巨大的 UGLY hack,并且在某些情况下仍然会出现问题 - 例如,当我在第一次编辑时点击视图时,有时当滚动视图停止减速时。
简而言之,发生的事情是发生了滚动事件(可能是由于上一行向上移动)并且iOS出于某种原因认为光标不在视图中。更奇怪的是,即使提供了错误的范围,它确实提供了正确的位置,从而将其滚动到视图中的错误位置。更奇怪的是,它只发生在某些条件下,并且只发生在条件发生的第二种情况下。我唯一能想到的是,删除文本后 UITextView 的高度计算不正确,它认为文本的位置与实际位置不同。
提前致谢!
更新:
我设置了我之前提到的标志scrollViewDidScroll:
,它不会阻止其他情况下的跳跃。但是,仍然存在向后删除文本仍然会跳过屏幕的情况。在视图仍然跳转的情况下更奇怪的是我看到我正在阻止[super scrollRangeToVisible]
被调用!所以在内部发生了一些事情,另外,这导致视图滚动。
更新:
它似乎在 613 点和 670 点之间向上跳跃。我不确定是什么导致了分数的差异。它跳跃的行数也不同。我怀疑条件之间必须有相似之处。此外,当scrollViewDidScroll:
被调用时,我验证了textView.selectedRange.location
此调用与委托调用之间的相同textViewDidChangeSelection:
。