2013-02-13 14 views
5

La mia app si arresta in modo anomalo durante la rimozione della vista di attesa dallo schermo. Per favore guidami come posso migliorare il codice indicato di seguito.La raccolta <CALayerArray: 0x1ed8faa0> è stata modificata mentre veniva enumerata


La visualizzazione di attesa viene richiamata solo quando l'app sta scaricando qualcosa dal server. e quando ha completato il download, chiamo il metodo removeWaitView.

Tipo eccezione: NSGenericException

Motivo: Collection è stato mutato mentre viene enumerato.

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

mia waitview codice aggiunta è

+(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

Sarebbe utile vedere il backtrace completo dell'eccezione. (Probabilmente Google è in giro se non sei sicuro di come trovare queste informazioni.) –

+1

Come viene chiamato 'removeWaitView'? – dasblinkenlight

risposta

13

L'eccezione è abbastanza chiaro - una collezione (in questo caso qualcosa di simile a un array) viene modificata mentre è inoltre in fase di enumerato.

In questo caso specifico, stiamo parlando di array di livelli, o meglio di istanze di UIView che sono tutte supportate da livelli.

Le modifiche si verificano quando si chiama removeFromSuperview o addSubview. L'enumerazione può avvenire in qualsiasi momento durante il ridisegno.

La mia ipotesi è: non stai chiamando i tuoi metodi dal thread principale e il thread principale è attualmente in fase di ridisegno, quindi avrai una condizione di gara.

Soluzione: chiamare questi metodi solo dal thread principale.

+0

hmm. Cerco sempre di chiamare metodi come questi sul thread principale ma mi sembra che tu abbia ragione perché questa eccezione può solo arrivare (secondo il mio codice) quando non viene chiamata dal thread principale. Ho ragione? –

+0

@Developer La risposta di Aaron Haymain è un'altra possibile spiegazione. Dovrebbe essere ovvio dalla traccia dello stack. – Sulthan

+1

Analisi molto intelligente. Grazie. – Martin

3

È possibile che si stia aggiungendo o rimuovendo un waitView mentre si sta iterando tra i fratelli waitView (sono le sottoview di superView). Controlla per vedere quali metodi chiamano removeWaitView e showWaitInView per assicurarti che i metodi di chiamata non chiamino i metodi mostra/rimuovi attesa della vista da all'interno di un ciclo for iterando i fratelli della vista di attesa (le sottoview della waitview's superview).

+0

sì, questo può creare problemi se avessi usato in un ciclo no non lo sto usando in un ciclo. Come avevo modificato la mia domanda, Grazie per informazioni –

+0

Felice di aiutare. Di solito, la mutazione esplicita all'interno di un ciclo è il colpevole più comune. Ma la mutazione può anche avvenire da un altro thread (che @sulthan ha sottolineato). –

5

Si dovrebbe ottenere una copia dell'array, in modo da non rischiare che venga modificato mentre il codice lo enumera. Ovviamente questo lascia la possibilità che un nuovo oggetto possa essere aggiunto come risultato della mutazione, quindi la tua numerazione mancherà a quell'elemento dell'array. Ecco un esempio specifico del titolo della tua domanda:

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

     }]; 
Problemi correlati