как вызвать метод нескольких аргументов с задержкой - PullRequest
39 голосов
/ 09 марта 2012

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

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

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

Я видел этот вопрос и Документация

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

например:

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

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

Спасибо

Ответы [ 6 ]

112 голосов
/ 09 марта 2012

использовать 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];
});

РЕДАКТИРОВАТЬ 2015: Для Swift, я рекомендую использовать этот маленький вспомогательный метод: dispatch_after - GCD в swift?

7 голосов
/ 09 марта 2012

Вы также можете реализовать метод в категории 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
6 голосов
/ 09 марта 2012

Другие идеи:

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]];
}
2 голосов
/ 25 октября 2014

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
    });
1 голос
/ 02 декабря 2015

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

0 голосов
/ 23 мая 2014

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

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

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

...