我有一个应用程序调用有时快速,有时慢的方法。我知道需要多长时间的上限(2秒)。我想设置一个计时器,以便在调用方法时启动,运行代码,但是直到2秒后才生成输出,无论实际需要多长时间。这样,用户将动作视为始终花费相同的时间。我该如何实现呢?
我想要的是这样的:
-(IBAction)doStuff {
// START A TIMER, LOOK BUSY
[activityIndicator startAnimating];
... real work happens here ...
... NSString *coolString gets assigned ...
// WHEN TIMER == 2 SECONDS, REVEAL COOLNESS
[activityIndicator stopAnimating];
[textField setText:coolString];
}
答案 0 :(得分:6)
有几种方法可以延迟Cocoa中的操作。最简单的方法是使用performSelector:withObject:afterDelay:
。此方法为您设置计时器,并在时间到来时调用指定的方法。这是一个NSObject
方法,因此您的对象都可以免费获得。
这里棘手的部分是第一个方法将阻塞主线程,所以你需要将它放到后台线程,然后返回主线程以更新UI。这是对它的抨击:
// 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!
}
我唯一能想到的是存储NSDate
中调用“work”方法的时间,并检查获得结果所需的时间。如果还不到两秒钟,请睡眠后台线程,然后在完成后回调主线程。
[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
}
}
答案 1 :(得分:0)
[self performSelector:@selector(myfunc) withObject: afterDelay:];
应该有帮助。
答案 2 :(得分:0)
-(IBAction)doStuff {
// START A TIMER, LOOK BUSY
[activityIndicator startAnimating];
... real work happens here ...
... NSString *coolString gets assigned ...
// WHEN TIMER == 2 SECONDS, REVEAL COOLNESS
[self performSelector:@selector(revealCoolnessWithString:) withObject:coolString afterDelay:2];
}
- (void)revealCoolnessWithString:(NSString *)coolString
{
[activityIndicator stopAnimating];
[textField setText:coolString];
}
希望这有帮助