如何调用具有时延的多参数方法

时间:2021-04-11 14:36:28

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:

如何使用performSelector:withObject:afterDelay调用这个方法?

Thanks

谢谢

6 个解决方案

#1


112  

use dispatch_after:

使用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?

编辑2015:对于Swift,我推荐使用这个小助手方法:dispatch_after - GCD in Swift ?

#2


7  

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:

您还可以使用nsincall对象(适用于iOS的所有版本)在NSObject的类别中实现方法。我想应该是这样的:

@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

#3


6  

Other ideas:

其他的想法:

1) You could use NSInvocations:

1)可以使用NSInvocations:

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

方法签名(NSMethodSignature *)签名(>>见Eldar Markov的答案)

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

文档:https://developer.apple.com/library/ios/文档/可可/引用/ /类/ NSInvocation_Class /引用/ 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]];
}

#4


2  

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

#5


1  

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

以下是如何在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

它作为标准函数包含在我的repo中:https://github.com/goktugyil/ezswiftextense

#6


0  

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.

设计用NSDictionary参数调用的方法。把你需要的东西放进去。

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.

如果您希望该方法也可以通过其他方式访问,那么可以调用一个方法来“解开”字典,并使用显式参数调用预期的方法。

#1


112  

use dispatch_after:

使用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?

编辑2015:对于Swift,我推荐使用这个小助手方法:dispatch_after - GCD in Swift ?

#2


7  

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:

您还可以使用nsincall对象(适用于iOS的所有版本)在NSObject的类别中实现方法。我想应该是这样的:

@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

#3


6  

Other ideas:

其他的想法:

1) You could use NSInvocations:

1)可以使用NSInvocations:

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

方法签名(NSMethodSignature *)签名(>>见Eldar Markov的答案)

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

文档:https://developer.apple.com/library/ios/文档/可可/引用/ /类/ NSInvocation_Class /引用/ 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]];
}

#4


2  

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

#5


1  

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

以下是如何在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

它作为标准函数包含在我的repo中:https://github.com/goktugyil/ezswiftextense

#6


0  

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.

设计用NSDictionary参数调用的方法。把你需要的东西放进去。

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.

如果您希望该方法也可以通过其他方式访问,那么可以调用一个方法来“解开”字典,并使用显式参数调用预期的方法。