ios - open - webview xcode 10
Accesos no reproducibles de webcore (2)
Tengo una aplicación para iPad que está en la tienda de aplicaciones por cerca de tres meses y he estado recibiendo algunos informes de fallos extraños que no puedo entender. Estos no son tan frecuentes, obtuvieron alrededor de 15-20 instancias desde el lanzamiento, pero siguen siendo lo suficientemente frecuentes como para molestarme. Los bloqueos son ligeramente diferentes (vea los rastros de la pila a continuación) pero como están relacionados con WebCore
supongo que tienen que ver con el uso de UIWebView
en la aplicación y pueden tener una causa común, aunque no soy 100% positivo. . El objetivo de implementación de la aplicación es iOS 6.0 pero los bloqueos aparecen en iPad 2, iPad 3 y iPad Mini, exclusivamente en iOS 7.
Solo hay un lugar en la aplicación donde estoy usando una vista web, para mostrar páginas web de artículos de noticias de varias fuentes. Tengo un controlador de vista para esto que tiene un UIWebView
como su vista. Hay una instancia de este controlador de vista que se encuentra en toda la aplicación, cada vez que se selecciona un nuevo artículo, la vista web existente se vuelve a cargar con la URL del artículo recientemente seleccionado.
Una de las soluciones propuestas, basada en la discusión sobre los problemas del WebCore, sugirió establecer la propiedad del delegate
webviews en nil
en el método de dealloc
del controlador. Lamentablemente, no creo que sea aplicable en mi caso porque el controlador de vista no se desasigna durante el ciclo de vida de la aplicación.
Otro problema podría ser las páginas web incorrectas que tienen referencias de imagen incorrecta en el CSS (bloqueo de loadPendingImages). Aunque no pude encontrar una página así todavía.
Además, verifiqué dos veces y me aseguré de realizar operaciones relacionadas con webview en el hilo principal.
Los choques son
Exception Type: EXC_BAD_ACCESS
Code: KERN_INVALID_ADDRESS
Con las siguientes trazas de pila (completas here )
0 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 815
1 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 788
2 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
3 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
4 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
5 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
y
0 WebCore WebCore::StyleResolver::loadPendingImages() + 1153
1 WebCore WebCore::ResourceRequestBase::~ResourceRequestBase() + 104
2 WebCore WebCore::StyleResolver::applyMatchedProperties(WebCore::StyleResolver::MatchResult const&, WebCore::Element const*) + 782
3 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 948
4 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
5 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
y
0 WebCore WebCore::StyleResolver::adjustRenderStyle(WebCore::RenderStyle*, WebCore::RenderStyle*, WebCore::Element*) + 19
1 WebCore WebCore::StyleResolver::styleForElement(WebCore::Element*, WebCore::RenderStyle*, WebCore::StyleSharingBehavior, WebCore::RuleMatchingBehavior, WebCore::RenderRegion*) + 964
2 WebCore WebCore::Document::styleForElementIgnoringPendingStylesheets(WebCore::Element*) + 96
3 WebCore WebCore::Element::computedStyle(WebCore::PseudoId) + 142
4 WebCore WebCore::ComputedStyleExtractor::propertyValue(WebCore::CSSPropertyID, WebCore::EUpdateLayout) const + 458
5 WebCore WebCore::CSSComputedStyleDeclaration::getPropertyValue(WebCore::CSSPropertyID) const + 42
y
0 WebCore WebCore::TimerBase::heapDeleteMin() + 37
1 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
2 WebCore WebCore::ThreadTimers::sharedTimerFiredInternal() + 94
3 WebCore WebCore::timerFired(__CFRunLoopTimer*, void*) + 24
4 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 14
5 CoreFoundation __CFRunLoopDoTimer + 782
¿Alguien ha experimentado choques similares? Si es así:
1. ¿Hay formas de replicarlos?
2. ¿Cómo se pueden depurar estos sin replicarlos?
3. ¿Qué arreglos solucionaron los problemas?
¡Gracias!
Mire su código Javascript-to-Objective-C y si está ejecutando / llamando código javascript, asegúrese de que la secuencia de comandos no invoque nuevas llamadas a Objective-C.
Este es el uso adecuado:
Javascript >> Objective-C
Objective-C >> Javascript
Esto es motivo de accidente:
Objective-C >> Javascript >> Objective-C
(aquí es posible un accidente dependiendo de algunas condiciones de carrera)
La solución es específica para el código de su proyecto. Pero lo más fácil sería envolver todo Javascript en setTimeout()
para programar la ejecución en el hilo de Javascript. Aquí hay un ejemplo simple, su código Objective-C necesita ejecutar este script:
storeUserPhoneNumber("011 123 4567");
Se producirá un storeUserPhoneNumber
si la función storeUserPhoneNumber
vuelve a llamar al código de Objective-C (directa o indirectamente) en su cuerpo. Para arreglar esto, simplemente envuelva el código en setTimeout como este:
setTimeout(function() {
storeUserPhoneNumber("011 123 4567");
}, 0);
Lo que esto logra es analizar el código Javascript de la cadena y colocarlo en la función que está programada para ejecutarse más adelante en el próximo tick de bucle de evento liberando el control de nuevo a Objective-C después de analizar el código JS.
Recuerde que necesita esta revisión en todas las llamadas Objective-C >> Javascript
;)
Tuve exactamente el mismo problema en una aplicación en la que trabajé, raramente solo ocurría en dispositivos más antiguos con iOS 7. Sospecho que esto tiene algo que ver con que no puedan mantenerse al día.
Lo que tenía era un UITableView
donde una de las filas abriría un UIViewController
que tenía un UIWebView
en él para anuncios personalizados. Lo que descubrí es que en los dispositivos más antiguos, los objetos y la memoria se liberaban con mayor frecuencia de lo que había visto en otras plataformas. Podía simular el bloqueo muy fácilmente en un iPhone 4 entrando / saliendo de la pantalla 2 o 3 veces. Donde como iPhone 5 pasé 15 minutos haciendo lo mismo y no pude encontrar fallas.
Sé que puede sentir que su controlador no está siendo desasignado pero realmente suena como si lo fuera o se está cayendo alguna referencia, también he visto cómo desaparecen algunas de mis referencias de delegado en esta aplicación.
Mi consejo y lo que funcionó para mí es detener la ejecución de la vista web y establecer todo en nil
cuando pueda.
En una instancia, en mi aplicación, elegí hacerlo en el viewWillDisappear
devolución de llamada, porque en mi caso se viewWillDisappear
del usuario y se volvió a crear más tarde, así que borré todo así:
[webView stopLoading];
self.webView.delegate = nil;
self.webView = nil;