how to call a method of multiple arguments with delay

36,582

Solution 1

use dispatch_after:

double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
    //code to be executed on the main queue after delay
    [self MoveSomethingFrom:from To:to];
});

EDIT 2015: For Swift, i recommend using this small helper method: dispatch_after - GCD in swift?

Solution 2

You can also implement method in NSObject's category using NSInvocation object (works in all versions of iOS). I guess it should be something like this:

@interface NSObject(DelayedPerform)

- (void)performSelector:(SEL)aSelector withObject:(id)argument0 withObject:(id)argument1  afterDelay:(NSTimeInterval)delay {

  NSMethodSignature *signature = [self methodSignatureForSelector:aSelector];

  NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
  [invocation setTarget:self];
  [invocation setSelector:aSelector];
  [invocation setArgument:&argument0 atIndex:2];
  [invocation setArgument:&argument1 atIndex:3];

  [invocation performSelector:@selector(invoke) withObject:nil afterDelay:delay];

}

@end

Solution 3

Other ideas:

1) You could use NSInvocations:

+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)signature
(>> see Eldar Markov's answer)

Documentation:
https://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html

2) You could use a helper method..

[self performSelector:@selector(helperMethod) withObject:nil afterDelay:delay];

- (void) helperMethod
{
    // of course x1 and x2 have to be safed somewhere else
    [object moveSomethigFrom: x1 to: x2];
}

3) You could use an array or a dictionary as parameter..

NSArray* array = [NSArray arrayWithObjects: x1, x2, nil];
[self performSelector:@selector(handleArray:) withObject:array afterDelay:delay];

- (void) handleArray: (NSArray*) array
{
    [object moveSomethigFrom: [array objectAtIndex: 0] to: [array objectAtIndex: 1]];
}

Solution 4

Swift:

    let delayInSeconds = 3.0;
    let delay = delayInSeconds * Double(NSEC_PER_SEC)
    let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay));
    dispatch_after(popTime, dispatch_get_main_queue(), {
        // DO SOMETHING AFTER 3 sec
    });

Solution 5

Here is how you can trigger a block after a delay in Swift:

runThisAfterDelay(seconds: 5) { () -> () in
    print("Prints this 5 seconds later in main queue")
    //Or perform your selector here
}

/// EZSwiftExtensions
func runThisAfterDelay(seconds seconds: Double, after: () -> ()) {
    let time = dispatch_time(DISPATCH_TIME_NOW, Int64(seconds * Double(NSEC_PER_SEC)))
    dispatch_after(time, dispatch_get_main_queue(), after)
}

The argument count does not really matter.

Its included as a standard function in my repo: https://github.com/goktugyil/EZSwiftExtensions

Share:
36,582
Frade
Author by

Frade

Updated on December 02, 2020

Comments

  • Frade
    Frade over 3 years

    I'm trying to call a method after some delay.

    I know there is a solution for that:

    [self performSelector:@selector(myMethod) withObject:nil afterDelay:delay];
    

    I saw this question and Documentation

    But my question is: How can I call a method that takes two parameters??

    for instance:

    - (void) MoveSomethigFrom:(id)from To:(id)to;
    

    How would I call this method with delay, using performSelector:withObject:afterDelay:

    Thanks

  • Alexander
    Alexander about 12 years
    Either that, or you can put as many parameters as you want in a container and send it as an argument for the performSelector: withObject: afterDelay method.
  • Eldar Markov
    Eldar Markov about 12 years
    you can use it in >= 3.2 as well. I just wanted to show that it's not necessary to use GCD. I'll edit my original answer)
  • Frade
    Frade about 12 years
    Ok.. I'm sorry but, what is GCD? what's the problem using it?
  • Frade
    Frade about 12 years
    I'm asking, because I have three answers and the 3 are good. Just trying to understand which is the best one to use. Thanks
  • Eldar Markov
    Eldar Markov about 12 years
    GCD - it's Grand Central Dispatch. Part of iOS sdk 4.0 and higher.If you want to use it in all versions of iOS use mine version)
  • Frade
    Frade about 12 years
    This seems a good approach, it really delays the call. But it happens something strange, the method doesn't do what is expected, does something else, that I can't even understand..
  • Frade
    Frade about 12 years
    got it.. It was some code that was executed during the delay.. thanks
  • Martin Ullrich
    Martin Ullrich about 12 years
    Yes if you really want to deploy on devices < 4.0 you have to stay away from GCD. But developing for iOS 4+ is safe as over 90% of active devices are running it and testing/coding effort is heavily reduced (assuming that you do serious testing)
  • Martin Ullrich
    Martin Ullrich about 12 years
    additionally, GCD improves code readability because because you don't have to have lots of methods being called asynchronously (you "just" have to get used to ^{}-Notations)
  • ArtOfWarfare
    ArtOfWarfare almost 11 years
    As a suggestion, don't reference other answers on SO as being "above" or "below", as they can be sorted more ways than one, and that most people sort by rating, which can be volatile. I suggest hitting the "share" button beneath the answer and sharing a link to it, for incase a question ends up with a large number of answers.
  • vir us
    vir us over 9 years
    is there a way to cancel scheduled call?
  • vir us
    vir us over 9 years
    if someone is interested this should work to cancel scheduled call (if performSelector:withObject:afterDelay: was used): [NSObject cancelPreviousPerformRequestsWithTarget:yourTarget selector:aSelector object: anArgument];
  • Martin Ullrich
    Martin Ullrich about 8 years
    @iEngineer: Sure u got everything right? i once used "MSEC_PER_SEC" instead of "NSEC_PER_SEC" which is 10^6 times faster.