it-roy-ru.com

iOS 7 Safari: ОС блокируется на 4 секунды при нажатии/фокусировке на вводе HTML

ОБНОВЛЕНИЕ: Кажется, проблема в том, что на странице много элементов выбора. Насколько это случайно?

Так вот в чем проблема. В iOS 7 Safari при нажатии на текстовый ввод на моем сайте открывается клавиатура, затем ОС останавливается примерно на 2-5 секунд, а затем, наконец, прокручивается до ввода. После того, как это произойдет один раз, это никогда не повторится, пока вы не обновите страницу. Я посмотрел повсюду, и да, iOS 7 Safari супер глючит, но давайте попробуем и посмотрим, сможем ли мы это выяснить. 

Примечание. Этого не происходит ни в каком другом мобильном браузере или в любом предыдущем iOS Safari. Это происходит как на ios 7 iphone, так и на ios 7 ipad.

Я перечислю все, что мой друг и я попробовал до сих пор:

  • Удалена возможность добавлять обработчики событий в jQuery. (Примечание: все наши обработчики событий назначаются через jQuery, кроме unload и onpageshow).
  • Удален скрипт автозаполнения jQuery из входных данных.
  • Удален весь JavaScript из входных данных.
  • Удалил все сторонние библиотеки, добавленные на страницу, отклонив домены на Mac.
  • Вернулся к предыдущим версиям jQuery. Последний, который мы могли использовать, пока ничего не получалось, был 1.7.0.
  • Вернулся к предыдущим версиям jQuery UI.
  • Изменена обработка входных событий, чтобы делегировать и жить, а не вкл ('click')
  • Удалены все CSS-классы.
  • Удалены все CSS со страницы. Примечание. Время отклика ОС уменьшилось до 1-2 секунд, но все же произошло.

У кого-нибудь есть какие-либо идеи?

Огромное спасибо!

38
transformerTroy

(Есть несколько несколько эффективных решений, см. В конце списка)

В моей компании мы тоже страдаем от этого. Мы подали вопрос в Apple, но слышали маму.

Вот некоторые интересные jsfiddles, чтобы проиллюстрировать некоторые из проблем, они определенно вращаются вокруг количества скрытых полей, и текстовые области, кажется, не затрагиваются.

Из отладочных работ, я предполагаю, что есть некоторая функциональность, пытающаяся определить, является ли ввод кредитной картой или номером телефона или каким-то особым видом, который, кажется, вызывает поведение блокировки. Это только одна гипотеза, хотя ..

Резюме:

На странице с формой, содержащей именованные элементы ввода внутри контейнеров, помеченных как «display: none», первое нажатие на вход в этой форме имеет очень заметную задержку (20 сек-2 мин) между приходом клавиатуры и фокусом ввода , Это не позволяет пользователям использовать наше веб-приложение из-за огромного времени, затрачиваемого на то, чтобы пользовательский интерфейс замер в ожидании ответа клавиатуры. Мы отладили его в различных сценариях, чтобы попытаться понять, что происходит, и, похоже, это связано с изменением в том, как iOS7 анализирует DOM по сравнению с тем, как это было в iOS6, у которого нет ни одной из этих проблем. 

Начиная с отладки в Safari Inspector с подключенным iPad, мы обнаружили, что iOS7 предоставляет гораздо больше информации о действиях (программы), до того момента, когда мы обнаружили, что _CollectFormMetaData является родителем проблемы. Поиск метаданных вызывает массовый отток, который увеличивается более чем линейно вместе с количеством скрытых контейнеров, содержащих входные данные. Мы обнаружили, что _isVisible и _isRenderedFormElement вызываются гораздо чаще, чем это должно быть разумно. Кроме того, если это поможет, мы обнаружили, что некоторые функции обнаружения, связанные с кредитными картами и адресными книгами, были очень популярными.

Вот некоторые jsFiddles для иллюстрации. Пожалуйста, просмотрите их в Safari на iPad под iOS6, а затем на iPad под iOS7:

http://jsfiddle.net/gUDvL/20/ - Отлично работает на обоих

http://jsfiddle.net/gUDvL/21/ - Просто заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/22/ - Более заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/29/ - ОЧЕНЬ заметная задержка на iOS 7

http://jsfiddle.net/gUDvL/30/ - То же, что и 29, но без скрытых - без задержки на iOS 7

http://jsfiddle.net/gUDvL/38/ - То же, что и 29, но усугубляется

http://jsfiddle.net/gUDvL/39/ - 99 скрытых входов, один видимый, один отдельно видимый

http://jsfiddle.net/gUDvL/40/ - 99 скрытых текстовых областей, одна видимая, одна отдельно видимая

http://jsfiddle.net/gUDvL/41/ - 99 скрытых входов, один видимый, один отдельно видимый, все с атрибутом autocomplete = "off"

http://jsfiddle.net/gUDvL/42/ - 99 скрытых входов, один видимый, один отдельно видимый. Скрыто по абсолютной позиции и оставлено вместо дисплея.

http://jsfiddle.net/gUDvL/63/ - То же, что и gUDvL/43 /, но с автозаполнением, автозаменой, автокапитализацией и проверкой орфографии

http://jsfiddle.net/gUDvL/65/ - То же, что и gUDvL/63 /, но с очищенным отступом (на iPad кажется медленнее)

http://jsfiddle.net/gUDvL/66/ - То же, что и gUDvL/65 /, но без отображения снова через css вместо DOMReady jQuery

http://jsfiddle.net/gUDvL/67/ - То же, что и gUDvL/66 /, но с техникой фокусировки/размытия ТедГрава

http://jsfiddle.net/gUDvL/68/ - То же, что и gUDvL/66 /, но с текстовым отступом, управляемым css, вместо отображения: снова блокировать (заметное улучшение - сокращение до 2-3 секунд для начального фокус)

http://jsfiddle.net/gUDvL/69/ - То же, что и gUDvL/68 /, но с фокусом TedGrav/добавлено размытие

http://jsfiddle.net/gUDvL/71/ - То же, что и gUDvL/66 /, но js добавляет тег легенды перед каждым вводом. (заметное улучшение - уменьшение до 2-3 секунд для начальной фокусировки)

<input type="text" autocomplete="off" /> (links to jsfiddle.net must be accompanied by code..)

(Следует отметить, что подключение iPad к компьютеру Mac с включенным отладчиком Safari резко усиливает задержки.)

Действия по воспроизведению:

  1. Загрузите любой из вышеперечисленных jsfiddles на iPad
  2. Нажмите вход, чтобы получить фокус
  3. Смотреть на экране, пока вы не можете набрать

Ожидаемые результаты:

Ожидайте, что сможете печатать, как только клавиатура появится

Фактические результаты:

Наблюдайте, как клавиатура всплывает и экран зависает, не в состоянии прокручиваться или взаимодействовать с Safari в течение продолжительного времени. После продолжительности фокус дается, как и ожидалось. С тех пор больше не происходит никаких зависаний при фокусировке на входах.

tl; dr краткое изложение техники

Итак, в целом есть пара предложенных исправлений из разных ответов:

  • Не скрывайте div с помощью display: none - используйте что-то вроде text-indent
  • Короткое замыкание Логика сканирования метаданных Apple - кажется, что многие теги форм или легенды делают свое дело
  • Автофокус/размытие - у меня не сработало, но два человека сообщили, что сработало

Похожие темы в Apple:

https://discussions.Apple.com/thread/5468360

13
Jasmine Hegman

Кажется, есть проблема с тем, как IOS обрабатывает touch-событие для входных данных и текстовых областей. Задержка становится больше, когда DOM становится больше. Однако с событием фокуса нет проблем!

Чтобы обойти эту проблему, вы можете переопределить событие touchend и установить фокус на input/textarea.

document.addEventListener("touchend", function (e) {  
     if (e.target.nodeName.toString().toUpperCase() == 'INPUT' || e.target.nodeName.toString().toUpperCase() == 'TEXTAREA') {  
         e.preventDefault(); 
         e.target.focus(); 
     } 
});

Это, однако, создаст новую проблему. Это позволит вам прокручивать страницу, касаясь ввода/текстовой области, но когда вы отпустите, сайт вернется в исходное положение.

Чтобы это исправить, вам просто нужно проверить, произошла ли прокрутка, и окружить protectDefault и target.focus оператором if.

Чтобы установить исходное положение, вы можете использовать событие touchstart .

document.addEventListener("touchstart", function (e) {
    ... //store the scrollTop or offsetHeight position and compare it in touchend event.
}

EDITЯ и коллега немного улучшили его, и он работает как шарм.

var scroll = 0; 
document.addEventListener("touchstart", function (e) { 
    scroll = document.body.scrollTop; 
 });   

document.addEventListener("touchend", function (e) { 
    if (scroll == document.body.scrollTop) { 
        var node = e.target.nodeName.toString().toUpperCase(); 
        if (node == 'INPUT' || node == 'TEXTAREA' || node == 'SELECT') { 
            e.preventDefault(); 
            e.target.focus(); 
            if(node != 'SELECT') {
                var textLength = e.target.value.length; 
                e.target.setSelectionRange(textLength, textLength);
            }
        } 
    } 
}); 
7
Binke

Боролся с этой проблемой также в полноэкранном режиме ios, который вставлял/удалял страницы, содержащие один элемент ввода. Были задержки до 30 секунд только с одним видимым элементом ввода текста на странице (и в пределах всего DOM). Другие динамически вставленные страницы с одним или несколькими текстовыми вводами в одном и том же веб-приложении не испытывали задержку ввода. Как уже упоминалось, после начальной задержки поле ввода будет вести себя нормально при последующих событиях фокуса (даже если динамическая страница, содержащая элемент ввода, была удалена из DOM, а затем динамически повторно визуализирована/вставлена ​​обратно в DOM).

На догадке, основанной на вышеупомянутом поведении, попробуйте следующее при загрузке страницы:

. $ ( "# Проблемно-вход") фокус (); .__ $ ( "# проблемно-вход") размывание ()..;

Хотя вышеперечисленное выполняется немедленно без задержки, конечный результат - отсутствие последующих задержек, когда ввод получает фокус при взаимодействии с пользователем. Не могу объяснить причину этой работы, но, похоже, она работает последовательно для моего приложения, в то время как другие предлагаемые исправления не помогли.

3
TedGrav

Основная проблема для меня была со скрытыми полями. Заставили форму зависать на 10-15 секунд.

Мне удалось обойти, поместив скрытые поля формы за пределы экрана.


Прятаться:

position: absolute;
left: -9999px;

Показывать:

position: relative;
left: 0;

3
Simon McFarlane

У меня та же проблема freezeing.

Я не уверен, что мы в такой же ситуации.

вот мое демо: http://tedzhou.github.io/demo/ios7sucks.html

На моей странице я использую элемент <p> с атрибутом onclick в качестве кнопки . Когда пользователь нажимает кнопку , страница меняется на textarea. Затем щелчок по нему замерзает браузер.

Время, затрачиваемое на заморозку, зависит от количества элементов dom. На моих страницах есть 10000 элементов, которые замораживаются на 10+ секунд.

Мы можем решить эту проблему, переключив элемент <p> на реальный <button> или уменьшив количество элементов dom.

pS: извините за мой плохой английский. лол

3
tedzhou

Для меня эта проблема была вызвана тем, что пользовательский ввод был скрыт на странице с display:none.

Обходной путь, который я использовал: вместо того, чтобы скрывать вводы с помощью display:none, я использовал метод jQuery detach() для документа, готового «скрыть» все пользовательские вводы, которые не использовались. Затем append() входы, когда они были необходимы.

Таким образом, при первой загрузке страницы не было ввода display:none, поэтому при первоначальном взаимодействии с пользователем задержки не возникали.

1
Dan Bamber

Это происходит не только в iOS, но и в safari 7 для MAC OS (Maverics). Я обнаружил, что проблема возникает, когда вы используете много тегов div для ввода (или выбора) внутри формы:

<div> <select>...</select> </div>
<div> <select>...</select> </div>
...

Я изменил компоновку моих выборок, чтобы использовать ul/li и fieldsets вместо div, и время замораживания было резко сокращено.

<ul>
   <li><select>...</select></div>
   <li><select>...</select></div>
</ul>

Вот два примера в jsfiddle:

заморозить на 5 секунд

http://jsfiddle.net/k3j5v/5/

заморозить на 1 секунду

http://jsfiddle.net/k3j5v/6/

Я надеюсь, что это может кому-то помочь

1
Raphael Isidro

Встречалась та же проблема в довольно сложном приложении, имеющем много входов. 

Подключен отладчик к Safari iOS7 через USB и регистрируется события пользовательского интерфейса. Я вижу, что событие "touchend" наступает, как только я нажимаю на textarea (или любой ввод), и через 10-20 секунд после этого я вижу отправку "click". 

Очевидно, это ошибка в Safary, поскольку на других устройствах, таких как Android или iOS6, нет проблем с тем же приложением.

1
c-smile

Мой ответ может быть немного не по главной теме, но я прибыл сюда после некоторого поиска, так как сценарий "кажется" похожим.

Результат:

Моя проблема ощущалась как блокировка в iOS, но не совсем, так как другие элементы на странице все еще были интерактивными. У меня был элемент <input type="search" />, который не фокусировался, когда я щелкал в поле. Но это в конечном итоге поймает фокус после примерно 4-5 нажатий на экран.

Дополнительная информация:

Мой проект - гибридное приложение: WebView внутри приложения iOS. Сайт создан с помощью Twitter Bootstrap.

Решение:

Мне также пришлось установить атрибут autofocus на элемент. Я попытался удалить это, и это сработало ... больше никаких последовательных нажатий, чтобы сфокусироваться на поле.

0
EdwardM

Я также столкнулся с этой проблемой, так как заметил, что у многих людей все еще есть проблема с этим, я думал, что поставлю свое решение.

В основном мое решение - сокрытие элементов на стороне сервера. Моя страница - ASP.NET, поэтому я обернул свои div с входами Panels и установил эти панели как Visible false . Таким образом, если я нажимаю на вход, сафари не может видеть все другие элементы управления, так как они скрыты на стороне сервера.

Конечно, если вы хотите сделать эту работу немного похожей на jquery на стороне клиента, вам понадобится автоматическая обратная передача и где-то панель обновления ........ Это решение требует усилий, но все же лучше, чем собственно попытка исправить ошибку сафари.

Надеюсь это поможет.

0
misha130

iOS 12.1.1 - декабрь 2018

Вот простое исправление, которое сработало в моем случае:

window.scrollTo(0,0) // прикреплено к событию 'blur' для полей ввода

Хотя он может быть не идеальным с точки зрения UX (особенно если у вас есть форма с большим количеством полей), это определенно лучше, чем время замораживания более 10 секунд.

0
SC1000

У нас была такая же или похожая проблема в моей компании. Всякий раз, когда мы отображали большое количество раскрывающихся списков, а затем пользователь нажимал на раскрывающийся список, IOS 7 останавливал страницу на одну или две минуты. После этого все будет работать правильно с этого момента. 

Это затронуло все типы ввода. Большое количество раскрывающихся списков было фактически скрыто при первой загрузке - пользователь мог инициировать отображение раскрывающихся списков. Пока не отобразились выпадающие списки - все будет работать нормально. Как только они отобразятся, следующий щелчок ввода, даже если он работал правильно, теперь приведет к зависанию браузера.

Как уже отмечалось, кажется, что IOS 7 имеет проблему при анализе видимых входных данных в DOM после того, как пользователь впервые взаимодействует с входными данными. Когда количество и/или сложность элементов/параметров/DOM выше, остановка становится более выраженной.

Поскольку при первоначальном взаимодействии с пользователем оно всегда зависало, мы решили инициировать скрытое действие пользователя, как только отобразим список выпадающих списков. Мы создали прозрачную кнопку (ее нельзя было скрыть - ее нужно было «отобразить») и инициировали щелчок по ней, как только пользователь открыл раскрывающийся список. Мы думали, что это заставит IOS начать разбор DOM быстрее, но обнаружили, что это фактически решило проблему полностью. 

0
Henry Fieger