2009-08-12 13 views
28

Ich stehe bei Abstürzen einer App, die UIWebView verwendet. Normalerweise ist es, wenn die Seite nicht vollständig geladen ist und UIWebView den Selektor stopLoading gesendet hat. Oder wenn UIWebView die Seite vollständig geladen hat. Ich habe EXC_BAD_ACCESS. Stapel sieht wie folgt aus:UIWebView EXC_BAD_ACCESS Absturz

#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 

für mich am meisten seltsame Sache hier ist webView:decidePolicyForNavigationAction:request:frame:decisionListener: Wähler auf UIWebView gesendet, weil es keine solche Wähler in UIWebView Dokumentation ist! Nur für Kakao (nicht Kakao Touch) WebView. Ich vermute, dass etwas mit UIWebView oder seinem Delegaten nicht stimmt. Aber ich kann keinen Haltepunkt setzen, um sie zu sehen. Bitte geben Sie an, wie ich in dieser Situation mehr Informationen erhalten kann.

+1

Was ist mit dem [UIWebView webView: decidePolicyForNavigationAction: Anfrage: frame: decisionListener:] ?? – Ahsan

Antwort

8

Versuchen Sie NSZombie einzuschalten und sehen Sie, ob etwas zu früh veröffentlicht wird.

Es kann sein, dass Sie das Laden der Ansicht abbrechen und dann sofort Ihre Ansichtshierarchie abreißen, was dazu führt, dass etwas freigegeben wird, bevor das UIWebView damit fertig wird.

In diesem Fall sieht das Backtrace deutlich wie es ist ein Delegat, das früh freigegeben wird. Delegieren Beziehungen sind in der Regel schwach und, ohne GC, sind eine wunderbare Quelle für dangling Referenzen, die Abstürze verursacht, die genau so aussehen.

+0

Schöne Antwort, das hilft mir, thx. – Joey

85

Sie haben die webView zu stoppen Laden und die Delegierten zu entfernen, bevor die Ansicht zu verlassen:

// 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]; 
} 

Was Apple-Dokumentation sagt: Wichtig: Bevor Sie eine Instanz von UIWebView Freigabe, für die Sie einen Delegaten festgelegt haben, Sie müssen zuerst die Eigenschaft delegate auf setzen. Dies kann beispielsweise in Ihrer Dealloc-Methode geschehen.

+0

Danke. Das löst mein EXC_BAD_ACCESS-Problem. –

+1

glücklich zu helfen :) – Ondrej

+3

In iOS 6 verwenden Sie dealloc-Methode mit ARC (ohne Aufruf von Super oder Speicherfreigabecode) - viewWillUnload ist in IOS 6 veraltet. –

1

Ich sah auch diesen genauen Fehler, und es wurde durch den Delegaten verursacht, den ich zu einem UIWebView bestimmt hatte, das nicht beibehalten wurde (in meinem Fall ein UIViewController).

2

Ich hatte einen EXC_BAD_ACCESS Absturz auf einem Scroll-UIWebView, aber nur auf dem iPad, und nur wenn der Benutzer das UIWebView Scrolling verlassen hatte, als er den View-Controller schloss, der es enthielt.

Das Festlegen der Delegat auf Null hat mein Problem hier nicht behoben, aber ich fand die Lösung anderswo unter einem anderen Problem. Ich habe diesen Code auf die von meinem Schließen-Schaltfläche namens Methode:

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

Dies das Scrollen stoppt, bevor die dealloc Methode aufgerufen wird, die das Problem zu sein scheint.

5

Ansicht verschwindet eine Arbeits Option auf die akzeptierte Antwort:

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

Dies funktioniert für iOS 6 perfekt.

0

Die Aufhebung der Registrierung des Delegaten aus der Webansicht und das Laden des Webview wird am besten über die Dealloc-Methode des ViewControllers gehandhabt.

Als Beispiel, wenn viewWillDisappear ausfallen kann:, wenn die Viewcontroller ein Kind eines anderen Viewcontroller ist, können Sie die Entfernung der nach Ansicht des Viewcontroller auslösen aus der Sicht der Eltern Viewcontroller mit einer Animation.Zur gleichen Zeit können Sie den ViewController von seinem Elternknoten entfernen und seine Referenz nicht entfernen. An diesem Punkt ist der ViewController gleich Null und viewWillDisappear wird niemals aufgerufen, was bedeutet, dass der WebView-Delegat niemals bereinigt wird.

Verwenden Sie dealloc und stellen Sie sicher, dass Ihr WebView immer bereinigt wird.

Verwandte Themen