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

Pen*_*One 4 cocoa-touch timer objective-c

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

}
Run Code Online (Sandbox Code Playgroud)

Jos*_*ell 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];
Run Code Online (Sandbox Code Playgroud)
- (void)doWorkForUnknownTime {

   // results is an ivar
   results = ...; // Perform calculations
}
Run Code Online (Sandbox Code Playgroud)
- (void)displayResults {
    if( !results ){
        // Make sure that we really got results
        [self performSelector:@selector(displayResults:)
                   withObject:nil
                   afterDelay:0.5];
        return;
    }

    // Do the display!
}
Run Code Online (Sandbox Code Playgroud)

我能想到的另一件事就是存储调用"work"方法的时间NSDate,并检查获得结果所花费的时间.如果还不是两秒钟,请睡眠后台线程,然后在完成后回调主线程.

[self performSelectorInBackground:@selector(doWorkForUnknownTime:)
                       withObject:[NSDate date]];
Run Code Online (Sandbox Code Playgroud)
- (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
    }
}
Run Code Online (Sandbox Code Playgroud)