Pregunta iOS 7 Safari: el sistema operativo se bloquea durante 4 segundos al hacer clic / enfocarse en una entrada HTML


ACTUALIZACIÓN: El problema parece provenir de tener muchos elementos seleccionados en una página. ¿Qué tan aleatorio es eso?

Así que aquí está el problema. En iOS 7 Safari, al tocar una entrada de texto en mi sitio, el teclado se abre y luego se congela el sistema operativo durante aproximadamente 2-5 segundos y finalmente se desplaza a la entrada. Después de que esto suceda una vez, nunca volverá a suceder hasta que actualice la página. He buscado por todos lados, y sí, iOS 7 Safari es muy caótico, pero intentemos ver si podemos resolver esto.

Nota: Esto no ocurre en ningún otro navegador móvil ni en ningún iOS Safari anterior. Sucede tanto en el ios 7 iphone como en el ios 7 ipad.

Enumeraré todo lo que mi amigo y yo hemos intentado hasta ahora:

  • Se eliminó la posibilidad de agregar manejadores de eventos en jQuery. (Nota: todos nuestros controladores de eventos se asignan a través de jQuery, excepto para descargar y mostrar páginas).
  • Se eliminó el script de autocompletar jQuery de las entradas.
  • Se eliminó todo el JavaScript de las entradas.
  • Se eliminaron todas las bibliotecas de terceros que se agregaron en la página al rechazar los dominios en la Mac.
  • Cambiado a las versiones anteriores de jQuery. El último que podríamos usar antes de que nada funcionara fue 1.7.0.
  • Cambié a las versiones anteriores de jQuery UI.
  • Se modificó el manejo de eventos de entrada para delegar y vivir, en lugar de hacerlo ('clic')
  • Se eliminaron todas las clases de CSS.
  • Se eliminó todo el CSS de la página. Nota: El tiempo de respuesta para el sistema operativo se redujo a 1-2 segundos, pero aún así sucedió.

¿Alguien tiene alguna idea?

¡Gracias un montón!


38
2017-10-12 14:09


origen


Respuestas:


(Hay algunas soluciones algo efectivas, ver cerca del final de la lista)

En mi compañía también estamos sufriendo por esto. Presentamos un problema con Apple pero hemos escuchado a mamá.

Aquí hay algunos jsfiddles interesantes para ayudar a ilustrar algunos de los problemas, definitivamente parece girar en torno a la cantidad de campos ocultos, y las áreas de texto no parecen verse afectadas.

Desde los esfuerzos de depuración, creo que hay alguna funcionalidad que intenta detectar si una entrada es una tarjeta de crédito o un número de teléfono o algún tipo especial que parece causar el comportamiento de bloqueo. Esta es solo una hipótesis, aunque ..

Resumen:

En una página con un formulario que contiene elementos de entrada con nombre dentro de contenedores que están marcados como "mostrar: ninguno", la primera vez que se presiona una entrada en esa forma tiene un retraso muy notable (20 segundos-2 minutos) entre el teclado que se acerca y la entrada enfocada . Esto impide que los usuarios usen nuestra aplicación web debido al enorme tiempo que se pasa con la interfaz de usuario congelada esperando que el teclado responda. Lo hemos depurado en varios escenarios para tratar de discernir qué está sucediendo, y parece ser un cambio en cómo iOS7 analiza el DOM en comparación con cómo lo hizo en iOS6, que no tiene ninguno de estos problemas.

Desde la depuración en Safari's Inspector con el iPad conectado, descubrimos que iOS7 proporciona mucha más información sobre las actividades (del programa), hasta el punto que encontramos que _CollectFormMetaData es el padre del problema. La búsqueda de metadatos provoca un abandono masivo que aumenta más que linealmente junto con la cantidad de contenedores ocultos que contienen entradas. Descubrimos que _isVisible y _isRenderedFormElement se llaman mucho más de lo que razonablemente deberían ser. Además, si ayuda, descubrimos que algunas funciones de detección relacionadas con las tarjetas de crédito y las libretas de direcciones eran grandes consumidores.

Aquí hay algunos jsFiddles para ilustrar. Mírelos en Safari en un iPad con iOS6 y luego en un iPad con iOS7:

http://jsfiddle.net/gUDvL/20/ - Funciona bien en ambos

http://jsfiddle.net/gUDvL/21/ - Retraso apenas notable en iOS 7

http://jsfiddle.net/gUDvL/22/ - Retraso más notable en iOS 7

http://jsfiddle.net/gUDvL/29/ - MUY notable retraso en iOS 7

http://jsfiddle.net/gUDvL/30/ - Igual que 29 pero sin ninguno oculto, sin demora en iOS 7

http://jsfiddle.net/gUDvL/38/ - Igual que el 29 pero aún más exacerbado

http://jsfiddle.net/gUDvL/39/ - 99 entradas ocultas, una visible, una visible por separado

http://jsfiddle.net/gUDvL/40/ - 99 áreas de texto ocultas, una visible, una visible por separado

http://jsfiddle.net/gUDvL/41/ - 99 entradas ocultas, una visible, una visible por separado, todo con el atributo autocompletar = "apagado"

http://jsfiddle.net/gUDvL/42/ - 99 entradas ocultas, una visible, una visible por separado. Oculto por posición absoluta e izquierda en lugar de mostrar.

http://jsfiddle.net/gUDvL/63/ - Igual que gUDvL / 43 / pero con autocompletar, autocorrección, autocapitalizar y corrección ortográfica

http://jsfiddle.net/gUDvL/65/ - Igual que gUDvL / 63 / pero con una sangría limpia (parece más lento en el iPad)

http://jsfiddle.net/gUDvL/66/ - Igual que gUDvL / 65 / pero con mostrar ninguno a través de css nuevamente en lugar de DOMReady jQuery

http://jsfiddle.net/gUDvL/67/ - Igual que gUDvL / 66 / pero con la técnica de enfoque / desenfoque de TedGrav

http://jsfiddle.net/gUDvL/68/ - Igual que gUDvL / 66 / pero con sangría de texto guiada por css en lugar de mostrar: bloquear de nuevo (mejora notable - reducción a 2-3 segundos para el enfoque inicial)

http://jsfiddle.net/gUDvL/69/ - Igual que gUDvL / 68 / pero con el foco / desenfoque de TedGrav re-agregado

http://jsfiddle.net/gUDvL/71/ - Igual que gUDvL / 66 / pero con js agregando una etiqueta de leyenda antes de cada entrada. (mejora notable - reducción a 2-3 segundos para el enfoque inicial)

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

(Debemos tener en cuenta que tener el iPad conectado a una Mac con el depurador de Safari comprometido dramáticamente enfatiza los retrasos).

Pasos para reproducir:

  1. Cargue cualquiera de los jsfiddles anteriores en el iPad
  2. Presione una entrada para obtener enfoque
  3. Mire la pantalla hasta que pueda escribir

Resultados previstos:

Espere poder escribir tan pronto como aparezca el teclado

Resultados actuales:

Mire el teclado emergente y la pantalla se congela, no puede desplazarse ni interactuar con Safari durante un tiempo. Después de la duración, el enfoque se da como se espera. A partir de ese momento, no se producirán más congelamientos al centrarse en las entradas.

tl; dr técnica resumen

Entonces, en general, hay un par de soluciones propuestas de varias respuestas:

  • No oculte los divs con display: ninguno - use algo como text-indent
  • Cortocircuito La lógica de escaneo de metadatos de Apple - muchas etiquetas de formularios o etiquetas de leyenda parecen hacer el truco
  • Enfoque automático / desenfoque: no funcionó, pero dos personas informaron que sí

Temas relacionados en Apple:

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


13
2018-01-30 00:12



Parece que hay un problema con la forma en que IOS maneja el evento táctil para entradas y áreas de texto El retraso se hace más grande cuando el DOM se hace más grande. ¡Sin embargo, no hay un problema con el evento de enfoque!

Para evitar este problema, puede anular el touchend evento y establecer foco a la entrada / textarea.

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

Sin embargo, esto creará un nuevo problema. Le permitirá desplazarse por la página mientras toca la entrada / área de texto, pero cuando la suelte, el sitio se desplazará nuevamente a la posición original.

Para solucionar esto, solo necesita comprobar si se ha producido algún desplazamiento, y rodear el preventDefault y target.focus con una declaración if.

Para establecer la posición original, puede usar touchstart evento.

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

EDITAR Yo y un colega lo hemos mejorado un poco, y funciona como un encanto.

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
2018-05-12 10:18



Tengo lo mismo freezeing problema.

No estoy seguro de que estemos en la misma situación.

aquí está mi demo:http://tedzhou.github.io/demo/ios7sucks.html

En mi página, uso un <p> elemento con onclick atributo como un botón. Cuando el usuario hace clic en el botón, cambio de página a textarea. Luego, al hacer clic en él, se congelará el navegador.

El tiempo de congelación pasó relevante para los números de los elementos dom. En mis páginas, hay 10000 elementos, que lo congelan por más de 10 segundos.

Podemos resolver el problema cambiando el <p> elemento a lo real <button>, o reduciendo los nums de los elementos dom.

PD: perdón por mi pobre inglés. LOL


3
2017-10-15 12:10



Lucharon con este problema también dentro de una pantalla completa ios que estaba insertando / eliminando páginas que contenían un solo elemento de entrada. Estaba experimentando retrasos de hasta 30 segundos con solo un elemento de entrada de texto visible en la página (y dentro de todo el DOM). Otras páginas insertadas dinámicamente con entradas de texto únicas o múltiples en la misma aplicación web no experimentaban el retraso de entrada. Como otros han mencionado, después del retraso inicial, el campo de entrada se comportaría normalmente en sucesos de enfoque subsiguientes (incluso si la página dinámica que contiene el elemento de entrada se eliminó del DOM, luego se volvió a renderizar dinámicamente / se insertó de nuevo en el DOM).

En una corazonada basada en el comportamiento anterior, intenté lo siguiente en la carga de la página:

$ ("# problem-input"). focus (); $ ("# problema-entrada"). desenfoque ();

Mientras que lo anterior se ejecuta inmediatamente sin demora, el resultado final no es el retraso posterior cuando la entrada se enfoca a través de la interacción del usuario. No puedo explicar el motivo de este trabajo, pero parece funcionar de manera consistente para mi aplicación, mientras que otras correcciones sugeridas han fallado.


3
2018-03-11 22:50



El problema principal para mí fue con los campos ocultos. Hizo que la forma se cuelgue durante 10-15 segundos.

Logré desplazarme colocando los campos ocultos fuera de la pantalla.


Esconder:

position: absolute;
left: -9999px;

Mostrar:

position: relative;
left: 0;


3
2017-12-16 12:53



Encontré el mismo problema en una aplicación bastante compleja que tiene muchas entradas.

Depurador adjunto a Safari iOS7 a través de USB y eventos de IU registrados. Veo el evento "touchend" tan pronto como hago clic en textarea (o cualquier entrada) y en 10-20 segundos veo que se envía "click".

Claramente, es un error en Safary ya que en otros dispositivos como Android o iOS6 no hay problema con la misma aplicación.


1
2017-11-22 00:35



Sucede no solo en iOS, sino también en Safari 7 para MAC OS (Maverics). He descubierto que el problema ocurre cuando se usan muchas etiquetas div para contener entradas (o selecciones) dentro de un formulario:

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

Cambié el diseño de mis selects para usar ul / li y fieldsets en lugar de divs y el tiempo de freezze se redujo drásticamente.

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

Aquí hay dos ejemplos en jsfiddle:

Freeze por 5 segundos

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

congelar por 1 segundo

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

Espero que pueda ayudar a alguien


1
2017-11-22 18:10



Para mí, este problema fue causado por entradas de usuario que se ocultan en la página con display:none.

La solución alternativa que utilicé: en lugar de ocultar las entradas con display:none, Utilicé jQuery's detach() método en el documento listo para 'ocultar' todas las entradas de usuario que no se estaban utilizando. Entonces append() las entradas cuando fueron necesarias.

De esa forma, no se tuvieron entradas display:none encendido cuando la página se cargó por primera vez y por lo tanto no se produjo ningún retraso en la interacción inicial del usuario.


1
2017-07-15 11:19