Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to call a method of multiple arguments with delay

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

like image 346
Frade Avatar asked Mar 09 '12 13:03

Frade


3 Answers

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?

like image 92
Martin Ullrich Avatar answered Nov 02 '22 21:11

Martin Ullrich


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]];
}
like image 6
calimarkus Avatar answered Nov 02 '22 21:11

calimarkus


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
like image 7
Eldar Markov Avatar answered Nov 02 '22 23:11

Eldar Markov