Я переписывал свое приложение для iOS 7. Теперь оно использует новый API TextKit. Я почти закончил, но есть еще одна проблема, которая вызывает у меня головную боль с тех пор, как я начал выполнять переход.
Проблема: когда я ввожу текст в UITextView, иногда представление будет прокручиваться вверх, скрывая курсор. Трудно точно определить узор, но, похоже, это происходит после того, как я удаляю строку, и текст ниже должен двигаться вверх. Но только ВТОРОЙ раз, когда я удаляю строку и ТОЛЬКО с определенными строками в документе (обычно строки, которые имеют только символ новой строки, но не всегда ...)
Я пробовал использовать эти решения в stackoverflow:
Как остановить UITextView от прокрутки вверх, когда вход в него
Прокрутите вниз UITextView неустойчиво в iOS 7 < / а>
Есть также много других проблем, при которых прокрутка работает некорректно при наличии UITableView в UITextView. На мой взгляд, у меня НЕТ таблиц.
Я хочу отметить, что я создал подклассы UITextView и обнаружил, что это определенно iOS 7, вызывающая не только прокрутку обзора вверх. Кроме того, что еще более странно, когда вы нажимаете кнопку «Назад» (чтобы удалить символ из UITextView), он отправляет два сообщения в textViewDidChangeSelection:
. Вот стек вызовов при возникновении проблемы. (Когда проблема не возникает, я все равно получаю два вызова для делегирования _2 _..., что кажется нормальным):
- Делегат UITextView
textViewDidChangeSelection:
содержит позицию удаляемого символа длиной один. (т.е. 1050,1) - Делегат UITextView
textViewDidChangeSelection:
вызывается снова и содержит ту же позицию, но с нулевой длиной. (т.е. 1050,0) - scrollViewDidScroll (до 3 раз, но обычно только один раз)
- Затем iOS 7 вызывает
UITextView.scrollRangeToVisible:
с диапазоном ПЕРВОГО вызова {1050,1}. Для меня это не имеет смысла. Я знаю, что это вызывается изнутри, а НЕ из какого-либо моего кода, потому что этот внутренний API называется_ensureselectionvisible
без какой-либо обратной связи с функцией, которую я, возможно, использовал для вызова события прокрутки.
Предположительно, первые два вызова - это просто выбор символа, а затем внутренний вызов deleteBackwards. В этом есть смысл. Но после этого я лечу вслепую. Я понятия не имею, почему он прокручивается или почему он вызывает scrollRangeToVisible:
с НЕПРАВИЛЬНЫМ диапазоном.
Мне удалось несколько смягчить проблему, переопределив UITextView.scrollRangeToVisible:
, вернув без вызова [super scrollRangeToVisible]
, когда пользователь редактирует текст. Я делаю это, отменяя некоторые вызовы делегата scrollview и устанавливая флаг, который говорит, что прокрутка не может происходить. Для меня это огромный УЖЕСТВЕННЫЙ взлом, и проблема все еще возникает в определенных ситуациях - например, когда я нажимаю на представление при первом редактировании, а иногда и когда представление прокрутки перестает замедляться.
Короче говоря, происходит событие прокрутки (вероятно, из-за перемещения предыдущей строки вверх), и iOS по какой-то причине думает, что курсора нет в представлении. Еще более любопытно то, что, даже если указан неправильный диапазон, он обеспечивает правильное положение, которое, в свою очередь, прокручивает его в неправильное место в представлении. Что еще более любопытно, так это то, что это происходит только в определенных условиях и только во втором случае, когда это условие возникает. Единственное, о чем я могу думать, это то, что высота UITextView не вычисляется правильно после удаления текста, и он считает, что текст находится в другом месте, чем он есть на самом деле.
Заранее спасибо!
ОБНОВИТЬ:
Я установил флаг, о котором говорил ранее в scrollViewDidScroll:
, и он не предотвращает скачки в некоторых других случаях. Однако бывают случаи, когда при удалении текста назад по-прежнему происходит переход на экран. Что еще более странно в случае, когда представление все еще перескакивает, так это то, что я вижу, что предотвращаю вызов [super scrollRangeToVisible]
! Итак, в ДОПОЛНЕНИИ что-то происходит внутри, что вызывает прокрутку представления.
ОБНОВИТЬ:
Кажется, что он прыгает между 613 и 670 очками вверх. Я не уверен, что вызывает разницу в баллах. Количество строк, которые он перескакивает, также варьируется. Я подозреваю, что что-то должно быть похожим между условиями. Кроме того, когда вызывается scrollViewDidScroll:
, я проверял, что textView.selectedRange.location
одинаково между этим вызовом и вызовом делегата textViewDidChangeSelection:
.