Ожидание определенной продолжительности в Cocoa

Есть ли более простой способ подождать определенное количество времени в Cocoa, чем то, что я придумал ниже?

- (void) buttonPressed {
 [self makeSomeChanges];
 // give the user some visual feedback and wait a bit so he can see it
 [self displayThoseChangesToTheUser];
 [self performSelector:@selector(buttonPressedPart2:) withObject:nil afterDelay:0.35];
}
- (void) buttonPressedPart2: (id)unused {
 [self automaticallyReturnToPreviousView];
}

Просто, чтобы быть ясным, нет проблемы с функциональным с этим кодом - моя единственная говядина - это стилистическая. В моем случае поток достаточно прост, что он работает, но попытайтесь инкапсулировать его или выбросить некоторые условные выражения, и все может стать уродливым. Мне было очень неловко, что я не мог найти способ подождать, а затем вернуться к той же точке кода, как этот (фиктивный) пример:

- (void) buttonPressed {
 [self doStuff];
 [UIMagicUnicorn waitForDuration:0.35];
 [self doStuffAfterWaiting];
}
7 ответов

Существует

usleep(1000000);

и

[NSThread sleepForTimeInterval:1.0f];

оба из которых будут спать в течение 1 секунды.


Здесь используется способ NSTimer. Это может быть даже уродливее, чем метод, который вы используете, но он позволяет повторять события, поэтому я предпочитаю его.

[NSTimer scheduledTimerWithTimeInterval:0.5f 
 target:self
 selector: @selector(doSomething:) 
 userInfo:nil
 repeats:NO];

Вы хотите избежать чего-то вроде usleep(), который просто повесит ваше приложение и заставит его чувствовать себя невосприимчивым.


Я не уверен, что он существует (пока), но с блоками в 10.6 (или PLBlocks в 10.5 и на iPhone) должно быть довольно легко написать небольшую обертку, например performBlock:afterDelay:, которая делает именно то, что вы хотите, без необходимости спать весь поток. Было бы действительно полезным кусочком кода.

Майк Эш написал об этом подобном в своем блоге:

NSString *something = ...;
RunAfterDelay(0, ^{
 NSLog(@"%@", something);
 [self doWorkWithSomething: something];
});


Что не так с простым usleep? Я имею в виду, за исключением "Cocoa чистоты", он все еще намного меньше, чем другие решения:)


Вероятно, вы захотите использовать NSTimer и отправить сообщение "doStuffAfterWaiting" в качестве своего обратного вызова. Любой "сон" блокирует поток, пока он не просыпается. Если это в вашем U.I. нить, это приведет к тому, что ваше приложение появится "мертвым". Даже если это не так, это плохая форма. Подход обратного вызова освободит CPU для выполнения других задач, пока не будет достигнут указанный вами временной интервал.

Этот doc содержит примеры использования и обсуждает различия в том, как и где создавать ваш таймер.

Конечно, performSelector: afterDelay: делает то же самое.


Tadah!

Чуть более информативный, ссылка указывает на NSThread sleepForTimeInterval:

Это было фактически украдено из: Что эквивалентно Java Thread.sleep() в Objective-C/Cocoa?


Если вы не против асинхронного решения, вы здесь:

[[NSOperationQueue currentQueue] addOperationWithBlock:^{
 [self doStuffAfterWaiting];
}];

licensed under cc by-sa 3.0 with attribution.