2009-08-12 10 views
28

Estoy experimentando bloqueos de una aplicación que utiliza UIWebView. Por lo general, es cuando la página no está completamente cargada y se envía a UIWebView el selector stopLoading. O cuando UIWebView carga la página por completo. Tengo EXC_BAD_ACCESS. Pila se ve así:UIWebView EXC_BAD_ACCESS bloqueo

#0 0x95bb7688 in objc_msgSend 
#1 0x30a671db in -[UIWebView webView:decidePolicyForNavigationAction:request:frame:decisionListener:] 
#2 0x3024a10d in __invoking___ 
#3 0x30249ff8 in -[NSInvocation invoke] 
#4 0x358ab160 in HandleDelegateSource 
#5 0x302452c1 in CFRunLoopRunSpecific 
#6 0x30244628 in CFRunLoopRunInMode 
#7 0x32044c31 in GSEventRunModal 
#8 0x32044cf6 in GSEventRun 
#9 0x309021ee in UIApplicationMain 
#10 0x0000239c in main at main.m:13 

para mí lo más extraño aquí es webView:decidePolicyForNavigationAction:request:frame:decisionListener: selector enviado a UIWebView, porque no hay tal selectora en la documentación UIWebView! Solo para Cocoa (no táctil al cacao) WebView. Sospecho que hay algo mal con UIWebView o su delegado. Pero no puedo establecer un punto de interrupción para verlos. Aconseja cómo puedo obtener más información en esta situación.

+1

¿Qué pasa con [UIWebView webView: decidePolicyForNavigationAction: request: frame: decisionListener:] ?? – Ahsan

Respuesta

8

Pruebe encender NSZombie y vea si algo se está liberando demasiado pronto.

Es posible que esté cancelando la carga de la vista y luego derribando inmediatamente la jerarquía de vista, lo que provoca que se libere algo antes de que UIWebView termine de jugar con él.

En este caso, la traza inversa se ve claramente como si fuera un delegado que se está liberando antes. Las relaciones de delegado suelen ser débiles y, al carecer de GC, son fuente maravillosa para referencias colgantes que provocan bloqueos que se ven así.

+0

Buena respuesta, esto me ayuda, gracias. – Joey

85

usted tiene que parar la carga de la web View y quite el delegado antes de salir de la vista:

// ARC (correct solution) 
- (void)dealloc { 
    [_webView setDelegate:nil]; 
    [_webView stopLoading]; 
} 

// non ARC 
- (void)dealloc { 
    [webView setDelegate:nil]; 
    [webView stopLoading]; 
    [webView release]; 
    [super dealloc]; 
} 

// ARC (older solution) 
- (void)viewWillUnload { 
    [webView setDelegate:nil]; 
    [webView stopLoading]; 
} 

¿Qué documentación de Apple está diciendo: Importante Antes de liberar una instancia de UIWebView para lo cual ha establecido un delegado, primero debe establecer su propiedad de delegado en cero. Esto se puede hacer, por ejemplo, en su método dealloc.

+0

Gracias. Esto resuelve mi problema EXC_BAD_ACCESS. –

+1

contento de ayudar :) – Ondrej

+3

En ios 6 use el método dealloc con ARC (sin llamar a super o ningún código de liberación de memoria) - viewWillUnload está en desuso en ios 6. –

1

También vi este error exacto, y fue causado por el delegado que había designado a un UIWebView que no se conserva (en mi caso, un UIViewController).

2

Estaba teniendo un bloqueo EXC_BAD_ACCESS en un UIWebView desplazable, pero solo en el iPad, y solo cuando el usuario dejó el desplazamiento de UIWebView cuando cerró el controlador de vista que lo contiene.

Configurar el delegado a cero no solucionó mi problema aquí, pero encontré la solución en otra parte con un problema diferente. He añadido este código al método llamado por mi botón de cierre:

for (id subview in webView.subviews){ 
     if ([[subview class] isSubclassOfClass: [UIScrollView class]]){ 
      [subview setContentOffset:CGPointZero animated:NO]; 
     } 
    } 

Esto detiene el desplazamiento antes de que el método se llama a dealloc, que parece ser el problema.

5

Ver desaparecerá es una opción de trabajo a la respuesta aceptada:

// ARC 
- (void)viewWillDisappear:(BOOL)animated{ 
    [self.webView setDelegate:nil]; 
    [self.webView stopLoading]; 
} 

Esto funciona para iOS 6 perfectamente.

0

El manejo de anular el registro del delegado desde la vista web y detener la carga de la vista web se maneja mejor desde el método dealloc de ViewController.

Como un ejemplo de cuando viewWillDisappear puede fallar: si el ViewController es un hijo de otro ViewController, puede desencadenar la eliminación de vista del ViewController desde el punto de vista de los padres ViewController con una animación.Al mismo tiempo, puede eliminar ViewController de su elemento primario y eliminar su referencia. En ese punto, ViewController será nulo y viewWillDisappear nunca se invocará, lo que significa que el delegado de WebView nunca se limpiará.

Utilice dealloc y asegúrese de que su WebView esté siempre limpia.