how to call a method of multiple arguments with delay

 ̄綄美尐妖づ 提交于 2019-11-28 17:12:26
Martin Ullrich

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?

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
calimarkus

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]];
}

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
    });

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

These will all work, but are all much more complex than is needed.

Design the method to be called with an NSDictionary argument. Put the objects in it you need.

If you want the method to be accessible by other means as well, call instead a method that 'unwraps' the dictionary and calls the intended method with explicit parameters.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!