Есть несколько способов отложить действие в Какао. Самым простым может быть использование performSelector:withObject:afterDelay:
. Этот метод устанавливает для вас таймер и вызывает указанный метод, когда придет время. Это метод NSObject
, поэтому все ваши объекты получают его бесплатно.
Сложность в том, что первый метод блокирует основной поток, поэтому вам нужно перевести его в фоновый поток, а затем вернуться в основной поток, чтобы обновить пользовательский интерфейс. Вот удар в этом:
// Put the method which will take a while onto another thread
[self performSelectorInBackground:@selector(doWorkForUnknownTime)
withObject:nil];
// Delay the display for exactly two seconds, on the main thread
[self performSelector:@selector(displayResults)
withObject:nil
afterDelay:2.0];
- (void)doWorkForUnknownTime {
// results is an ivar
results = ...; // Perform calculations
}
- (void)displayResults {
if( !results ){
// Make sure that we really got results
[self performSelector:@selector(displayResults:)
withObject:nil
afterDelay:0.5];
return;
}
// Do the display!
}
Единственное, о чем я могу думать, - это сохранить время, когда метод "work" вызывается в NSDate
, и проверить, сколько времени прошло, когда вы получите результаты. Если это еще не две секунды, переведите фоновый поток в спящий режим, а затем перезвоните основному потоку, когда закончите.
[self performSelectorInBackground:@selector(doWorkForUnknownTime:)
withObject:[NSDate date]];
- (void)doWorkForUnknownTime:(NSDate *)startTime {
// All threads must have an autorelease pool in place for Cocoa.
@autoreleasepool{
// This will take some time
NSString * results = ...; // Perform calculations
NSTimeInterval elapsedTime = [[NSDate date] timeIntervalSinceDate:startTime];
if( elapsedTime < 2.0 ){
// Okay to do this to wait since we're on a background thread,
// although not ideal; sleeping threads are kind of wasteful.
// Try not to do this a lot.
sleep(2.0 - elapsedTime);
}
// Don't forget to retain results on the main thread!
[self performSelectorOnMainThread:@selector(displayResults:)
withObject:results
waitUntilDone:YES];
// [results release]; // if necessary
}
}