wake-up-neo.com

Blöcke statt performSelector: withObject: afterDelay:

Ich möchte in Zukunft oft einige Mikrosekunden Code ausführen. Im Moment löse ich es so:

- (void)someMethod
{
    // some code
}

Und das:

[self performSelector:@selector(someMethod) withObject:nil afterDelay:0.1];

Es funktioniert, aber ich muss jedes Mal eine neue Methode erstellen. Ist es möglich, stattdessen Blöcke zu verwenden? Grundsätzlich suche ich eine Methode wie:

[self performBlock:^{
    // some code
} afterDelay:0.1];

Das wäre wirklich nützlich für mich.

87
Rits

Es gibt keine eingebaute Möglichkeit, dies zu tun, aber es ist nicht schlecht, dies über eine Kategorie hinzuzufügen:

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay 
{
    block = [[block copy] autorelease];
    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block {
    block();
}

@end

Dank an Mike Ash für die grundlegende Implementierung.

106
John Calsbeek

Hier ist eine einfache Technik, die auf GCD basiert und die ich verwende:

void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
      dispatch_get_current_queue(), block);
}

Ich bin kein GCD-Experte und würde mich über Kommentare zu dieser Lösung freuen.

41
Nick Moore

Ein anderer Weg (vielleicht der schlechteste Weg, dies aus vielen Gründen zu tun) ist:

[UIView animateWithDuration:0.0 delay:5.0 options:UIViewAnimationOptionAllowUserInteraction animations:^{
} completion:^(BOOL finished) {
    //do stuff here
}];
22
ninjaneer

Wenn Sie speziell eine längere Verzögerung benötigen, funktionieren die obigen Lösungen einwandfrei. Ich habe @ nicks Ansatz mit großem Erfolg angewendet.

Wenn Sie jedoch möchten, dass Ihr Block während der nächsten Iteration der Hauptschleife ausgeführt wird, können Sie ihn mit den folgenden Schritten noch weiter verkleinern:

[[NSOperationQueue mainQueue] addOperationWithBlock:aBlock];

Dies ist vergleichbar mit performSelector: mit afterDelay von 0.0f

16
Greg Combs

Ich habe ähnlichen Code wie diesen verwendet:

double delayInSeconds = 0.2f;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
      //whatever you wanted to do here...  
    });
11
Despotovic

Es gibt eine nette, vollständige Kategorie, die diese Situation hier behandelt:

https://Gist.github.com/95512

1
Duane Fields