Подтвердить что ты не робот

Как вызвать метод множественных аргументов с задержкой

Я пытаюсь вызвать метод после некоторой задержки.

Я знаю, что для этого есть решение:

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

Я видел этот вопрос и Documentation

Но мой вопрос: как я могу вызвать метод, который принимает два параметра

например:

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

Как я могу вызвать этот метод с задержкой, используя performSelector:withObject:afterDelay:

Спасибо

4b9b3361

Ответ 1

использовать 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 в быстром?

Ответ 2

Вы также можете реализовать метод в категории NSObject, используя объект NSInvocation (работает во всех версиях 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

Ответ 3

Другие идеи:

1) Вы можете использовать NSInvocations:

+ (NSInvocation *)invocationWithMethodSignature:(NSMethodSignature *)signature
( → см. ответ Эльдара Маркова)

Документация:
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]];
}

Ответ 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
    });

Ответ 5

Вот как вы можете запускать блок после задержки в 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

Ответ 6

Все это будет работать, но все гораздо сложнее, чем нужно.

Создайте метод, который будет вызываться с помощью аргумента NSDictionary. Поместите нужные вам объекты.

Если вы хотите, чтобы этот метод был доступен другим способом, вызовите вместо этого метод, который "разворачивает" словарь и вызывает метод, с явным параметром.