Как вызвать метод множественных аргументов с задержкой
Я пытаюсь вызвать метод после некоторой задержки.
Я знаю, что для этого есть решение:
[self performSelector:@selector(myMethod) withObject:nil afterDelay:delay];
Я видел этот вопрос и Documentation
Но мой вопрос: как я могу вызвать метод, который принимает два параметра
например:
- (void) MoveSomethigFrom:(id)from To:(id)to;
Как я могу вызвать этот метод с задержкой, используя performSelector:withObject:afterDelay:
Спасибо
Ответы
Ответ 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. Поместите нужные вам объекты.
Если вы хотите, чтобы этот метод был доступен другим способом, вызовите вместо этого метод, который "разворачивает" словарь и вызывает метод, с явным параметром.