2013-03-11 5 views
57

Мне нужно добавить задержку между выполнением двух строк в (той же) функции. Есть ли какие-либо благоприятные варианты для этого?Добавление задержки между выполнением двух следующих строк

Примечание: Для этого мне не нужны две разные функции, и задержка не должна влиять на выполнение других функций.

например:

line 1: [executing first operation]; 

line 2: Delay      /* I need to introduce delay here */ 

line 3: [executing second operation]; 

Любая помощь заметна. Заранее спасибо ...

ответ

149

Вы можете использовать НОД, чтобы сделать это без того, чтобы создать еще один метод

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

Правильно предупреждать людей об этом, но если вы программируете контроллеры, которым необходимо дождаться внешнего устройства с фиксированным временем обработки, это НЕ НЕПРЕРЫВНО. – user2161301

+2

Как насчет задержки HTTP-запроса при записи в строке поиска? Фильтрация результатов при наборе текста? Ожидая одну секунду, прежде чем запрашивать отфильтрованный список, вместо того, чтобы запрашивать сервер для каждого ключа, пользовательские отводы не кажутся мне бессмысленными. –

17

Эта строка вызывает селектор secondMethod через 3 секунды:

[self performSelector:@selector(secondMethod) withObject:nil afterDelay:3.0 ]; 

Используйте его на второй операции с нужной задержкой. Если у вас много кода, поместите его в свой собственный метод и вызовите этот метод с помощью performSelector:. Оно не блокирует пользовательский интерфейс, как sleep

Edit: Если вы не хотите второй метод, который вы могли бы добавить категорию, чтобы иметь возможность использовать блоки с 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); 
} 
+6

ОП явно заявляет, что они не хотят, второй метод: S –

+0

Он мог бы добавить категорию, чтобы иметь возможность использовать блоки с 'performSelector': http://stackoverflow.com/questions/4007023/blocks-instead -отверстиеизменения с помощью объекта – Sunkas

+0

@Sunkas: Спасибо за ответ. Но я уже упоминал, что не хочу добавлять вторую функцию. –

2

Если вы ориентируетесь 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]; 
}); 
+1

Вы имеете в виду iOS 4? [Ссылка на центральную диспетчерскую отправку] (http://developer.apple.com/library/ios/documentation/Performance/Reference/GCD_libdispatch_Ref/Reference/reference.html#//apple_ref/doc/uid/TP40008079-CH2-SW3) –

23

вы можете использовать NSThread метод:

[NSThread sleepForTimeInterval: delay]; 

Однако, если вы сделаете это в основном потоке вы будете блокировать приложение, так что делать это только на фоне потока.


или Swift

NSThread.sleepForTimeInterval(delay) 

в Swift 3

Thread.sleep(forTimeInterval: delay) 
+0

Я считаю, что это должен был быть принятый ответ в соответствии с требованиями вопроса. – ACLima

+1

@ACLima: Извините, «sleepForTimeInterval» будет спать в течение заданного интервала времени, что может повлиять на выполнение других одновременных функций. –

+0

@ KrishnaRajSalim я вижу, спасибо – ACLima

8

У меня есть несколько пошаговых игр, где мне нужно ИИ, чтобы сделать паузу, прежде чем принимать его поворот (и между этапами в свою очередь). Я уверен, что есть другие, более полезные ситуации, когда задержка - лучшее решение. В 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 были разные (мне нужно, чтобы добавить это, что один, тоже..)

0

Как @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: или performSelectorOnMainThread: withObject: waitUntilDone: режимы: метод для гарантии, что ваш селектор выполняет в основном потоке. Чтобы отменить сообщение , используйте метод cancelPreviousPerformRequestsWithTarget: или cancelPreviousPerformRequestsWithTarget: selector: object:.

Смежные вопросы