2016-05-05 15 views
0

Ich brauche 1 s Verzögerung in For-Schleife, aber es funktioniert nicht. Ich muss Tabellenansicht Zelle mit 1 Sekunde Verzögerung mit Animation entfernen, so wird es nacheinander entfernen. Derzeit löschen alle Zeilen gleichzeitig. Für Schleife ist bereits in Dispatch_after für 3 Sekunden, so über alles verschachtelte Dispatch_after.Out Seite die For-Schleife dispatch_after funktioniert.dispatch_after funktioniert nicht in Schleife auf ios

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
    for(int i=array_messages.count;i>0;i--) 
    { 
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
      [array_messages removeObjectAtIndex:0]; 
      NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:indexPath.section]; 
      [self.tableViewMessage deleteRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationTop]; 
      }); 

    } 
    }); 
+0

Warum sollten sie nicht? Sie versenden seriell, aber ohne Verzögerung zwischen den Versendungen. Sie müssen es rekursiv machen - jeden Dispatch-Block den nächsten Löschvorgang veranlassen. – Avi

+0

Ich bestätige das. Nach der Verwendung von Grand Central Dispatch für Jahre und Jahre muss ich sagen, dass GCD viele Probleme hat. Abhängig von der Art des Codes, den Sie entwickeln, funktionieren GCD-Mechanismen einfach nicht wie erwartet. Ich musste heute einen Code ersetzen, wo ein Block gefeuert wurde, gefolgt von einem dispatch_after-Code, um den Vorgang Sekunden später abzubrechen, weil das Ganze nicht auf iPhone 5 funktionierte. Derselbe Code funktionierte perfekt auf iPhone 6. Beide unter iOS 9.3. 2. Auf dem iPhone 5 wurde die Nachricht "dispatch_after" vor der angegebenen Zeit ausgelöst.Ich empfehle stattdessen NSOperationQueue zu verwenden. – SpaceDog

Antwort

1

Ihre for Schleife wird fast sofort durch die gesamte Sequenz iterieren, was bedeutet, dass Ihre inneren dispatch_after Anrufe werden fast zur gleichen Zeit eingestellt, und so wird etwa zur gleichen Zeit, die Sie sehen, ausgeführt werden.

Sie würden wahrscheinlich in diesem Fall mit einer NSTimer besser bedient werden. Etwas wie folgt aus:

Eine NSTimer Eigenschaft zu verwenden:

@property (strong) NSTimer* deletionTimer = nil; 

diese Methoden Ihrer Klasse hinzufügen:

- (void)startDeletionTimer { 
    [self killDeletionTimer]; 
    self.deletionTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(deletionTimerFired:) userInfo:nil repeats:YES]; 
} 

- (void)killDeletionTimer { 
    [self.deletionTimer invalidate]; 
    self.deletionTimer = nil; 
} 

- (void)deletionTimerFired:(NSTimer*)timer { 
    NSUInteger numberOfRecords = [array_messages count]; 

    if (!numberOfRecords) { 
     // None left, we're done 
     [self killDeleteionTimer]; 
     return; 
    } 

    [array_messages removeObjectAtIndex:0]; 
    [self.tableViewMessage deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:indexPath.section]] withRowAnimation:UITableViewRowAnimationTop]; 
} 

einleiten Timer mit diesem:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 
    [self startDeletionTimer]; 
}); 

Diese hat einige Vorteile gegenüber Optionen mit dem inneren dispatch_after mit einer Verzögerung. Es wird gnädig Änderungen im array_messages Array handhaben, da seine Zählung bei jeder Iteration überprüft wird, nicht am Anfang angenommen. Wenn Sie zum Beispiel 30 Nachrichten haben, dauert Ihr gesamter Löschvorgang 30 Sekunden. Wenn eine neue Nachricht in diesem Zeitraum hinzugefügt wird, oder schlimmer noch, eine Nachricht wird irgendwie entfernt, stürzt Ihre App ab, wenn die letzte dispatch_after auslöst, da der Index und/oder die Zeile nicht existiert. Ähnlich verhält es sich, wenn der Benutzer von der Ansicht weg navigiert, kann die Tabellensicht aufgehoben werden und Sie werden dann abstürzen.

Ein weiterer Vorteil ist, wenn in diesen 30 Sekunden, während es langsam/schmerzhaft zeigt die Datensätze gelöscht werden, der Benutzer nur weitergehen will, können Sie den Timer beenden und löschen Sie einfach alle Zeilen auf einmal.

+0

Awsome, es funktioniert gut. Vielen Dank @Dave Wood – DJtiwari

+0

NP, froh, zu helfen :) –

0

den Code unten verwenden Sie den Code Ausführung

double delayInSeconds = 1.0; 
dispatch_time_t disTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC)); 
dispatch_after(disTime, dispatch_get_main_queue(), ^(void){ 
    //place your code 
}); 

Lassen Sie mich zu verzögern, wenn Sie irgendwelche Probleme haben.

+0

Nein, es funktioniert nicht. Ich habe diesen Code in for-Schleife implementiert. – DJtiwari

0

diese versuche ich praktisch bin nicht versucht, so sicher nicht

for(int i=array_messages.count;i>0;i--) 
        { 

         int delay = (array_messages.count - i) + 1; 
         dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC), dispatch_get_main_queue(), ^{ 


          [array_messages removeObjectAtIndex:0]; 

          NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:indexPath.section]; 

          [self.tableViewMessage deleteRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationTop]; 
         }); 

        } 
-1

@ DJTiwari Dieses es Arbeit Versuchen

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void){ 
    //Background Thread 
    dispatch_async(dispatch_get_main_queue(), ^(void){ 
     for(int i=array_messages.count;i>0;i--) 
     { 
      [NSThread sleepForTimeInterval:1]; 
      [array_messages removeObjectAtIndex:0]; 
      NSIndexPath *path = [NSIndexPath indexPathForRow:0 inSection:indexPath.section]; 
      [self.tableViewMessage deleteRowsAtIndexPaths:[NSArray arrayWithObject:path] withRowAnimation:UITableViewRowAnimationTop]; 
     } 
    }); 
}); 
+1

Sie wollen nicht '[NSThread sleepForTimeInterval: 1];' in Code auf dem Haupt-Thread ausgeführt werden. Dadurch wird die App komplett gesperrt, da Sie diese in den 'dispatch_async (dispatch_get_main_queue()') Block eingefügt haben. –

+0

@DaveWood Ich habe diesen Code versucht, es ist perfectly –

+0

Ich werde nicht mit dir streiten, ich bin sicher, es sieht so aus, als ob es funktioniert, aber ich wette, wenn Sie eine Reihe von Objekten im Array haben, ist Ihre App gesperrt und Sie können nicht einmal die TableView nach oben/unten scrollen, während es seine Sache macht (schlafen) 'sleepForTimeInterval' auf dem Hauptthread (oder in der Hauptwarteschlange, die auf dem Hauptthread ausgeführt wird.) Ever. –

1

Sie nicht Verzögerung auf 'for-Schleife' setzen können. Wenn Sie etwas mit einer Verzögerung wiederholen möchten, verwenden Sie NSTimer.

+0

Dank @rakeshNS, es funktioniert gut mit NSTimer – DJtiwari