web-dev-qa-db-ja.com

複数の引数のメソッドを遅延して呼び出す方法

少し遅れてメソッドを呼び出そうとしています。

私はそのための解決策があることを知っています:

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

この質問ドキュメント を見ました

しかし、私の質問は次のとおりです。2つのパラメーターを取るメソッドを呼び出すにはどうすればよいですか?

例えば:

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

performSelector:withObject:afterDelay:を使用して、このメソッドを遅延して呼び出す方法

ありがとう

39
Frade

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:Swiftの場合、この小さなヘルパーメソッドを使用することをお勧めします: dispatch_after-GCD in swift?

112
Martin Ullrich

NSInvocationオブジェクトを使用してNSObjectのカテゴリにメソッドを実装することもできます(iOSのすべてのバージョンで動作します)。私はそれがこのようなものであるべきだと思います:

@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
7
Eldar Markov

他のアイデア:

1)NSInvocationsを使用できます:

+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)signature
(>> Eldar Markov's answerを参照

ドキュメンテーション:
https://developer.Apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html

2)ヘルパーメソッドを使用できます。

[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)パラメータとして配列または辞書を使用できます。

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

迅速:

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

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

引数の数は実際には重要ではありません。

それは私のレポの標準機能として含まれています: https://github.com/goktugyil/EZSwiftExtensions

1
Esqarrouth

これらはすべて機能しますが、必要以上に複雑です。

NSDictionary引数で呼び出されるメソッドを設計します。必要なオブジェクトを入れてください。

メソッドに他の手段でもアクセスできるようにする場合は、代わりに辞書を「アンラップ」し、明示的なパラメーターを使用して目的のメソッドを呼び出すメソッドを呼び出します。

0
tooluser