Добавление задержки между выполнением двух следующих строк
Мне нужно добавить задержку между выполнением двух строк в (той же) функции. Есть ли какие-либо благоприятные варианты для этого?
Примечание. Мне не нужны две разные функции, и задержка не должна влиять на выполнение других функций.
например:
line 1: [executing first operation];
line 2: Delay /* I need to introduce delay here */
line 3: [executing second operation];
Любая помощь заметна. Спасибо заранее...
Ответы
Ответ 1
Вы можете использовать gcd для этого, не создавая другого метода
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
NSLog(@"Do some work");
});
Вы все равно должны спросить себя: "Мне действительно нужно добавить задержку", поскольку он часто может усложнять код и вызывать условия гонки.
Ответ 2
Вы можете использовать метод NSThread
:
[NSThread sleepForTimeInterval: delay];
Однако, если вы сделаете это в основном потоке, вы заблокируете приложение, так что сделайте это только в фоновом потоке.
или в Swift
NSThread.sleepForTimeInterval(delay)
в Swift 3
Thread.sleep(forTimeInterval: delay)
Ответ 3
Эта строка вызывает селектор secondMethod через 3 секунды:
[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ];
Используйте его во второй операции с требуемой задержкой. Если у вас много кода, поместите его в свой собственный метод и вызовите этот метод с помощью performSelector:
. Он не будет блокировать пользовательский интерфейс, как sleep
Изменить: Если вы не хотите использовать второй метод, вы можете добавить категорию, чтобы иметь возможность использовать блоки с функцией performSelector:
@implementation NSObject (PerformBlockAfterDelay)
- (void)performBlock:(void (^)(void))block
afterDelay:(NSTimeInterval)delay
{
block = [block copy];
[self performSelector:@selector(fireBlockAfterDelay:)
withObject:block
afterDelay:delay];
}
- (void)fireBlockAfterDelay:(void (^)(void))block
{
block();
}
@end
Или, возможно, даже более чистый:
void RunBlockAfterDelay(NSTimeInterval delay, void (^block)(void))
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, NSEC_PER_SEC*delay),
dispatch_get_current_queue(), block);
}
Ответ 4
У меня есть пара пошаговых игр, в которых мне нужен ИИ, чтобы сделать паузу, прежде чем начать свою очередь (и между шагами в свою очередь). Я уверен, что есть другие, более полезные ситуации, когда задержка - лучшее решение. В Swift:
let delay = 2.0 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) { self.playerTapped(aiPlayView) }
Я только что вернулся, чтобы узнать, были ли вызовы Objective-C разными. (Мне тоже нужно добавить это к этому.)
Ответ 5
Если вы ориентируетесь на iOS 4.0+, вы можете сделать следующее:
[executing first operation];
double delayInSeconds = 2.0;
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
[executing second operation];
});
Ответ 6
Как пишет @Sunkas, performSelector:withObject:afterDelay:
- это кулон для dispatch_after
, только что он короче и у вас обычный синтаксис objective-c
. Если вам нужно передать аргументы блоку, который вы хотите отложить, вы можете просто передать их через параметр withObject
, и вы получите его в selector
, который вы вызываете:
[self performSelector:@selector(testStringMethod:)
withObject:@"Test Test"
afterDelay:0.5];
- (void)testStringMethod:(NSString *)string{
NSLog(@"string >>> %@", string);
}
Если вы по-прежнему хотите выбрать себя, если выполняете его в основном потоке или в текущем потоке, существуют определенные методы, которые позволяют вам указать это. Документация "Яблоки" сообщает следующее:
Если вы хотите, чтобы сообщение было отменено, когда цикл выполнения находится в режиме кроме режима по умолчанию, используйте performSelector: withObject: afterDelay: inModes: метод вместо этого. если ты не уверены, является ли текущий поток основным потоком, вы можете используйте функцию performSelectorOnMainThread: withObject: waitUntilDone: или выполнитьSelectorOnMainThread: withObject: waitUntilDone: режимы: метод для убедитесь, что ваш селектор выполняет основной поток. Чтобы отменить сообщение в очереди, используйте cancelPreviousPerformRequestsWithTarget: или cancelPreviousPerformRequestsWithTarget: селектор: объект: метод.