2013-02-13 6 views
5

Meine App stürzt einige Zeit ab, während die Warteansicht vom Bildschirm entfernt wird. Bitte führen Sie mich, wie kann ich den unten angegebenen Code verbessern.Sammlung <CALayerArray: 0x1ed8faa0> wurde während der Aufzählung mutiert


Die Warteansicht wird nur aufgerufen, wenn die App etwas vom Server herunterlädt. und wenn es Download abgeschlossen hat, dann rufe ich removeWaitView Methode auf.

Ausnahmetyp: NSGenericException

Grund: Collection wurde, während sie aufgezählt mutiert.

+(void) removeWaitView:(UIView *) view{ 
    NSLog(@"Shared->removeWaitView:"); 
    UIView *temp=nil; 
    temp=[view viewWithTag:kWaitViewTag]; 
    if (temp!=nil) { 
     [temp removeFromSuperview]; 
    } 
} 

mein waitview Hinzufügen von Code ist

+(void) showWaitViewInView:(UIView *)view withText:(NSString *)text{ 
    NSLog(@"Shared->showWaitViewWithtag"); 
    UIView *temp=nil; 
    temp=[view viewWithTag:kWaitViewTag]; 
    if (temp!=nil) 
    { 
     return; 
    } 
    //width 110 height 40 
    WaitViewByIqbal *waitView=[[WaitViewByIqbal alloc] initWithFrame:CGRectMake(0,0,90,35)]; 
    waitView.center=CGPointMake(view.frame.size.width/2,(view.frame.size. height/2) -15); 
    waitView.tag=kWaitViewTag; // waitView.waitLabel.text=text; 
    [view addSubview:waitView]; 
    [waitView release]; 
} 
+0

Es wäre nützlich, das vollständige Zurückverfolgen der Ausnahme zu sehen. (Sie können Google wahrscheinlich umrunden, wenn Sie nicht sicher sind, wie Sie diese Informationen finden können.) –

+1

Wie wird 'removeWaitView' aufgerufen? – dasblinkenlight

Antwort

13

Die Ausnahme ist ziemlich klar - eine Sammlung (in diesem Fall so etwas wie ein Array) geändert wird, während es auch aufgezählt wird.

In diesem speziellen Fall sprechen wir über Array von Schichten, oder besser gesagt, Instanzen von UIView, die alle von Schichten gesichert werden.

Die Änderungen werden ausgeführt, wenn Sie removeFromSuperview oder addSubview aufrufen. Die Aufzählung kann jederzeit während des Neuzeichnens erfolgen.

Meine Vermutung ist - Sie rufen nicht Ihre Methoden aus dem Haupt-Thread und der Haupt-Thread wird derzeit neu gezeichnet, so dass Sie eine Renn-Bedingung bekommen.

Lösung: rufen Sie diese Methoden nur aus dem Hauptthread.

+0

hmm. Ich versuche immer, Methode wie diese auf Hauptgewinde aufzurufen, aber es scheint mir, dass Sie Recht haben, weil diese Ausnahme nur kommen kann (nach meinem Code), wenn es nicht aus dem Haupt-Thread aufgerufen wird. Habe ich recht? –

+0

@Developer Aaron Haymains Antwort ist eine andere mögliche Erklärung. Es sollte offensichtlich von Ihrem Stack-Trace sein. – Sulthan

+1

Sehr intelligente Analyse. Vielen Dank. – Martin

3

Es ist möglich, dass Sie waitView hinzufügen oder entfernen, während Sie die Geschwister von waitView durchlaufen (es sind die Unteransichten von superView). Überprüfen Sie, welche Methoden die Methoden removeWaitView und showWaitInView aufrufen, um sicherzustellen, dass die aufrufenden Methoden die show/remove wait view-Methoden nicht innerhalb einer for-Schleife aufrufen, die die Geschwister der waitView (die Unterviews der superview) iteriert.

+0

Ja, das kann zu Problemen führen, wenn ich in einer Schleife nein verwendet habe, ich verwende es nicht in einer Schleife. Da ich meine Frage bearbeitet hatte, danke für Informationen –

+0

Froh, zu helfen. Normalerweise ist eine explizite Mutation innerhalb einer Schleife der häufigste Schuldige. Die Mutation kann aber auch von einem anderen Thread kommen (worauf @sultan hinweist). –

5

Sie sollten eine Kopie des Arrays erhalten, damit Sie nicht riskieren, dass es geändert wird, während Ihr Code es aufzählt. Natürlich lässt dies die Möglichkeit, dass ein neues Element als Ergebnis der Mutation hinzugefügt werden kann, daher wird Ihre Aufzählung diesen einen Array-Eintrag verpassen. Hier ein Beispiel für den Titel Ihrer Frage:

[[viewLayer.sublayers copy] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { 
      CALayer * subLayer = obj; 
      if(subLayer == theLayerToBeDeleted){ 
       [subLayer removeFromSuperlayer]; 
      } 

     }]; 
Verwandte Themen