如何使方法在固定的时间内停止?

时间:2011-05-25 05:05:25

标签: objective-c cocoa-touch timer

我有一个应用程序调用有时快速,有时慢的方法。我知道需要多长时间的上限(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];

}

3 个答案:

答案 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];
}

希望这有帮助