sirve que puedo porque para paginas mac internet descargar conecta carga algunas abrir abre javascript iphone ipad webkit mobile-webkit

puedo - El navegador iPad/iPhone se bloquea al cargar imágenes en Javascript



safari no carga paginas (11)

Archivé un error con jQuery cuando jQuery intenta manejar fugas de memoria ... así que lo consideraría un error. Esperemos que el equipo pueda llegar a una forma concisa e inteligente de manejar este problema en Mobile Safari pronto.

http://dev.jquery.com/ticket/6944#preview

Intento crear una galería de imágenes en Safari que imita la aplicación de fotos del iPad. Funciona perfectamente, excepto que una vez que cargo más de 6 MB de imágenes, ya sea agregándolas al DOM o creando nuevos objetos de imagen, las nuevas imágenes dejan de cargarse o el navegador se cuelga. Este problema es lo suficientemente extendido (con todos los demás chocando contra el mismo límite) que he descartado mi código JavaScript como el culpable.

Dado que puede transmitir mucho más que unos pocos MB en un elemento o mediante el reproductor multimedia en el navegador, este límite parece innecesario, y debería haber algún tipo de solución disponible. Tal vez liberando memoria o algo más.

También encontré esta referencia para UIWebView .

"Las asignaciones de JavaScript también están limitadas a 10 MB. Safari genera una excepción si supera este límite en la asignación total de memoria para JavaScript".

Que coincide con lo que estoy viendo bastante bien. ¿Es posible desasignar objetos en Javascript, o Safari / UIWebView mantiene un total acumulado y nunca lo suelta? Alternativamente, ¿hay alguna solución alternativa para cargar los datos de otra manera que no consuma estos 10MB?


En una aplicación de rieles, estaba perezosa cargando cientos de fotos medianas (desplazamiento infinito) e inevitablemente toco el límite de 10 Mb en el iphone. Traté de cargar los gráficos en un lienzo (nueva imagen, src =, luego Image.onload) pero todavía alcanzo el mismo límite. También traté de reemplazar el img src y quitarlo (cuando salió del área visible) pero todavía no había ningún cigarro. Al final, el hecho de cambiar todas las etiquetas img w / div''s w / the photo como fondo hizo el truco.

$.ajax({ url:"/listings/"+id+"/big", async:true, cache:true, success:function(data, textStatus, XMLHttpRequest) { // detect iOS if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/iPad/i)) { // load html into data data = $(data); // replace img w/ div w/ css bg data.find(".images img").each(function() { var src = $(this).attr("src").replace(//s/g,"%20"); var div = $("<div>"); div.css({width:"432px",height:"288px",background:"transparent url("+src+") no-repeat"}); $(this).parent().append(div); $(this).remove(); }); // remove graphic w/ dynamic dimensions data.find(".logo").remove(); } // append element to the page page.append(data); } });

Ahora puedo cargar más de 40Mb de fotos en una página sin golpear la pared. Sin embargo, me encontré con un problema extraño, ya que algunos de los gráficos de fondo CSS no se muestran. Un hilo de js rápido lo solucionó. Establezca la propiedad css bg del div cada 3 segundos.

setInterval(function() { $(".big_box .images div.img").each(function() { $(this).css({background:$(this).css("background")}); }); }, 3000);

Puede ver esto en acción en http://fotodeck.com . Compruébalo en tu iphone / ipad.


Hasta ahora he tenido suerte usando etiquetas <div> lugar de etiquetas <img> y estableciendo la imagen como la imagen de fondo del div.

En general, es una locura Si el usuario hace una solicitud afirmativa de más contenido de imagen, entonces no hay ninguna razón por la cual Safari no deba permitirle cargarlo.


Hay problemas con la memoria y la forma de resolver este problema es muy simple. 1) Pon todas tus miniaturas en lienzo. Creará muchos objetos de Imagen nuevos y los dibujará en lienzo, pero si su miniatura es muy pequeña, debería estar bien. Para el contenedor donde se mostrará la imagen de tamaño real, cree solo un objeto de imagen y reutilice este objeto y asegúrese de dibujarlo también en un lienzo. Por lo tanto, cada vez que un usuario hace clic en la miniatura, actualizará su objeto de Imagen principal. No inserte etiquetas IMG en la página. Inserte etiquetas CANVAS con el ancho y alto correctos de las miniaturas y el contenedor de la pantalla principal. iPad lanzará una falta si inserta demasiadas etiquetas IMG. Entonces, evítenlos !!! Insertar solo lienzo A continuación, puede encontrar el objeto canvas de la página y obtener el contexto. Por lo tanto, cada vez que el usuario haga clic en una miniatura, obtendrá el src de la imagen principal (imagen de tamaño real) y lo dibujará en el lienzo principal, reutilizando el objeto principal de la imagen y disparando los eventos. Limpiando los eventos cada vez al principio.

mainDisplayImage.onload = null; mainDisplayImage.onerror = null; ... mainDisplayImage.onload = function() { ... Draw it to main canvas } mainDisplayImage.onerror = function() { ... Draw the error.gif to main canvas } mainDisplayImage.src = imgsrc_string_url;

He creado 200 miniaturas y cada una es como 15kb. Las imágenes reales son como 1 MB cada una.


He tenido suerte comenzando con la sugerencia de Steve Simitzis y Andrew.

Mi proyecto:

Aplicación basada en PhoneGap con 6 secciones principales, y alrededor de 45 subsecciones que tienen una galería de ciclos jquery de entre 2 y 7 imágenes, cada una de 640 x 440 (más de 215 imágenes). Al principio estaba usando ajax para cargar fragmentos de página, pero desde entonces he cambiado a un sitio de una página, con todas las secciones ocultas hasta que sea necesario.

Inicialmente, después de recorrer unas 20 galerías, recibí una advertencia de memoria 1, luego 2 y luego el bloqueo.

Después de hacer todas las imágenes en divs con la imagen aplicada como fondo, pude atravesar más galerías (alrededor de 35) en la aplicación antes de un colapso, pero después de ir a las galerías previamente visitadas, eventualmente fallaría.

La solución que parece funcionar para mí es almacenar la URL de la imagen de fondo en el atributo del título del div y configurar todas las imágenes de fondo para que sean un gif en blanco. Con más de 215 imágenes, quería guardar la url en algún lugar del html para mayor facilidad y referencia rápida.

Cuando se presiona un botón de subnavegación, reescribo la imagen de fondo css a la fuente correcta que está contenida en la etiqueta del título del div, para SÓLO la galería que se muestra. Esto me salvó de tener que hacer cualquier javascript elegante para almacenar la imagen de origen correcta.

var newUrl = $(this).attr(''title''); $(this).css(''background-image'', ''url(''+newUrl+'')'');

Cuando se presiona un nuevo botón de subnavegación, reescribo la imagen de fondo de los últimos divs de la galería para que sean gifs en blanco. Entonces, aparte de la interfaz gfx, solo tengo de 2 a 7 imágenes ''activas'' en todo momento. Con cualquier otra cosa que agregue que contenga imágenes, simplemente uso esta técnica "ondemand" para cambiar el título con la imagen de fondo.

Ahora parece que puedo usar la aplicación indefinidamente sin fallas. No sé si esto ayudará a alguien más, y puede que no sea la solución más elegante, pero me proporcionó una solución.


Los límites de descarga de 6.5MB (iPad) / 10MB (iPhone) se calculan en función del número de elementos de imagen utilizados para establecer una imagen a través de su propiedad src. El safari móvil no parece diferenciar las imágenes cargadas del caché o de la red. Tampoco importa si la imagen se inyecta en el dom o no.

La segunda parte de la solución es que el safari móvil parece ser capaz de cargar un número ilimitado de imágenes a través de la propiedad css "background-image".

Esta prueba de concepto utiliza un grupo de precacher que establece las propiedades de la imagen de fondo una vez descargadas con éxito. Sé que no es óptimo y no devuelve el programa de descarga de imágenes utilizado al grupo, pero estoy seguro de que entiendes :)

La idea está adaptada de la solución alternativa original de Rob Laplaca http://roblaplaca.com/blog/2010/05/05/ipad-safari-image-limit-workaround/

<!DOCTYPE html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>iPad maximum number of images test</title> <script type="text/javascript"> var precache = [ new Image(), new Image(), new Image(), new Image() ]; function setImage(precache, item, waiting) { precache.onload = function () { item.img.style.backgroundImage = ''url('' + item.url + '')''; if (waiting.length > 0) { setImage(precache, waiting.shift(), waiting); } }; precache.src = item.url; } window.onload = function () { var total = 50, url = ''http://www.roblaplaca.com/examples/ipadImageLoading/1500.jpg'', queue = [], versionUrl, imageSize = 0.5, mb, img; for (var i = 0; i < total; i++) { mb = document.createElement(''div''); mb.innerHTML = ((i + 1) * imageSize) + ''mb''; mb.style.fontSize = ''2em''; mb.style.fontWeight = ''bold''; img = new Image(); img.width = 1000; img.height = 730; img.style.width = ''1000px''; img.style.height = ''730px''; img.style.display = ''block''; document.body.appendChild(mb); document.body.appendChild(img); queue.push({ img: img, url: url + ''?ver='' + (i + +new Date()) }); } // for (var p = 0; p < precache.length; p++) { if (queue.length > 0) { setImage(precache[p], queue.shift(), queue); } } }; </script> </head> <body> <p>Loading (roughly half MB) images with the <strong>img tag</strong></p> </body> </html>


Me encontré con una memoria insuficiente con Javascript en el iPad cuando estábamos tratando de actualizar una imagen muy a menudo, como cada dos segundos. Era un error actualizarlo a menudo, pero Safari se estrelló en la pantalla de inicio. Una vez que tuve el tiempo de actualización bajo control, la aplicación web funcionó bien. Parecía que el motor de JavaScript no podía seguir el ritmo de la recolección de basura lo suficientemente rápido como para descartar todas las imágenes antiguas.


No pude encontrar una solución para esto. Aquí hay un par de métodos que probé, y todos fallaron:

  • Simplemente cambió el fondo de un DIV usando div.style.backgroundImage = "url("+base64+")"

  • Cambió el .src de una imagen usando img.src = base64

  • Se eliminó la imagen anterior y se agregó la nueva utilizando removeChild( document.getElementById("img") ); document.body.appendChild( newImg ) removeChild( document.getElementById("img") ); document.body.appendChild( newImg )

  • Lo mismo que arriba, pero con una altura aleatoria en la nueva imagen

  • Eliminar y agregar la imagen como un objeto canvas de HTML5. Tampoco funciona, ya que una nueva Image(); tiene que ser creado, ver *

  • En el lanzamiento, creó un nuevo objeto Image() , vamos a llamarlo contenedor. Visualicé la imagen como <canvas> , cada vez que cambiaba la imagen, cambiaba el .src del .src y .src dibujar el lienzo usando ctx.drawImage( container, 0,0 ) .

  • Los sames como el anterior, pero sin volver a dibujar el lienzo en realidad. Simplemente cambiando el src del objeto Image() agota la memoria.

Algo extraño que noté: ¡el error ocurre incluso si la imagen no se muestra! Por ejemplo, al hacer esto:

var newImg = new Image( 1024, 750 ); newImg.src = newString; // A long base64 string

Cada 5 segundos, y nada más, no cargar o mostrar la imagen, por supuesto envuelto en un objeto, también bloquea la memoria después de un tiempo.


También estoy corriendo en un problema similar en Chrome, desarrollando una extensión que carga imágenes en la misma página (la ventana emergente, en realidad) reemplazando imágenes viejas por imágenes nuevas. La memoria utilizada por las imágenes antiguas (eliminadas del DOM) nunca se libera, consumiendo toda la memoria de la PC en poco tiempo. Ha intentado varios trucos con CSS, sin éxito. Usando hardware con menos memoria que una PC, como el iPad, este problema surge antes, naturalmente.


También tuve problemas similares al generar grandes listas de imágenes en iPhones. En mi caso, mostrar incluso 50 imágenes en la lista fue suficiente para bloquear el navegador o, ocasionalmente, todo el sistema operativo. Por alguna razón, las imágenes que se representan en la página no se recogen basura, incluso cuando se reúnen y reciclan solo unos pocos elementos DOM en pantalla o usando las imágenes como propiedad de imagen de fondo. Incluso mostrar las imágenes directamente como Data-URI es suficiente para contar hacia el límite.

La solución terminó siendo bastante simple: el uso de la position: absolute en los ítems de la lista les permite ser recolectados con la basura lo suficientemente rápido como para no encontrarse con un límite de memoria. Esto todavía involucra tener solo alrededor de 20-30 imágenes en el DOM en cualquier momento, creando y eliminando los nodos DOM del elemento por la posición de desplazamiento finalmente hizo el truco.

Parece que es particularmente dependiente de tener webkit-transform'':''scale3d() aplicado a cualquier antecesor de las imágenes en el DOM. Relativamente fluye un DOM muy alto y lo renderiza en la GPU molesta una pérdida de memoria en el renderizador webkit, supongo?


Actualización: creo que hay una manera aún más fácil de hacerlo, dependiendo de su aplicación. En lugar de tener múltiples imágenes, si solo tiene un elemento <img> u objeto Image (o tal vez dos, como una "esta" imagen y una "siguiente" si necesita animaciones o transiciones) y simplemente actualice el .src .width .height , etc., nunca debe acercarse al límite de 10 MB. Si desea hacer una aplicación de carrusel, primero debe usar marcadores de posición más pequeños. Es posible que encuentre que esta técnica podría ser más fácil de implementar.

Creo que en realidad pude haber encontrado una solución a esto.

Básicamente, necesitarás hacer una gestión más profunda de la imagen y reducir de forma explícita cualquier imagen que no necesites. Normalmente harías esto usando document.removeChild(divMyImageContainer) o $("myimagecontainer").empty() o lo que sea, pero en Mobile Safari esto no hace absolutamente nada; el navegador simplemente nunca desasigna la memoria.

En su lugar, necesita actualizar la imagen en sí, por lo que ocupa muy poca memoria; y puedes hacerlo cambiando el atributo src la imagen. La forma más rápida que conozco de hacer eso es usar una URL de datos . Entonces, en lugar de decir esto:

myImage.src="/path/to/image.png"

... di esto en cambio:

myImage.src="data:image/gif;base64,AN_ENCODED_IMAGE_DATA_STRING"

A continuación hay una prueba para demostrar que funciona. En mis pruebas, mi gran imagen de 750 KB finalmente mataría al navegador y detendría toda la ejecución de JS. Pero después de reiniciar src , he podido cargar instancias de la imagen más de 170 veces. También hay una explicación de cómo funciona el código.

var strImagePath = "http://path/to/your/gigantic/image.jpg"; var arrImages = []; var imgActiveImage = null var strNullImage = "data:image/gif;base64,R0lGODlhEAAOALMAAOazToeHh0tLS/7LZv/0jvb29t/f3//Ub//ge8WSLf/rhf/3kdbW1mxsbP//mf///yH5BAAAAAAALAAAAAAQAA4AAARe8L1Ekyky67QZ1hLnjM5UUde0ECwLJoExKcppV0aCcGCmTIHEIUEqjgaORCMxIC6e0CcguWw6aFjsVMkkIr7g77ZKPJjPZqIyd7sJAgVGoEGv2xsBxqNgYPj/gAwXEQA7"; var intTimesViewed = 1; var divCounter = document.createElement(''h1''); document.body.appendChild(divCounter); var shrinkImages = function() { var imgStoredImage; for (var i = arrImages.length - 1; i >= 0; i--) { imgStoredImage = arrImages[i]; if (imgStoredImage !== imgActiveImage) { imgStoredImage.src = strNullImage; } } }; var waitAndReload = function() { this.onload = null; setTimeout(loadNextImage,2500); }; var loadNextImage = function() { var imgImage = new Image(); imgImage.onload = waitAndReload; document.body.appendChild(imgImage); imgImage.src = strImagePath + "?" + (Math.random() * 9007199254740992); imgActiveImage = imgImage; shrinkImages() arrImages.push(imgImage); divCounter.innerHTML = intTimesViewed++; }; loadNextImage()

Este código fue escrito para probar mi solución, por lo que tendrás que descubrir cómo aplicarlo a tu propio código. El código viene en tres partes, que explicaré a continuación, pero la única parte realmente importante es imgStoredImage.src = strNullImage;

loadNextImage() simplemente carga una nueva imagen y llama a shrinkImages() . También asigna un evento de carga que se utiliza para comenzar el proceso de carga de otra imagen (error: debería estar limpiando este evento más tarde, pero no lo estoy).

waitAndReload() solo está aquí para permitir que aparezca la imagen en la pantalla. Mobile Safari es bastante lento y muestra imágenes grandes, por lo que necesita tiempo después de que la imagen se haya cargado para pintar la pantalla.

shrinkImages() recorre todas las imágenes cargadas previamente (excepto la activa) y cambia el .src a la dirección del banco de datos.

Estoy usando una imagen de carpeta de archivo para la columna de datos aquí (fue la primera imagen de columna de datos que pude encontrar). Lo estoy usando simplemente para que pueda ver el script funcionando. Probablemente prefiera usar un gif transparente, así que use esta cadena de url de datos en su lugar: data:image/gif;base64,R0lGODlhAQABAIAAAP///wAAACH5BAEAAAAALAAAAAABAAEAAAICRAEAOw==