问题
I want to be able to execute a delay every time that a function loops through a loop. I already have a loop setup, as shown below:
for (float batteryPercentage = 1; batteryPercentage <= 0; batteryPercentage -= 0.01)
{
double timeUntilNextDegreeDrop = 9.0;
dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(timeUntilNextDegreeDrop * NSEC_PER_SEC));
dispatch_after (time, dispatch_get_main_queue(), ^(void)
{
[batteryLevel setProgress:batteryPercentage animated:YES];
float batteryLevelPercentage = batteryPercentage * 100;
batteryLevelLabel.text = [NSString stringWithFormat:@"Battery Level: %f%%", batteryLevelPercentage];
});
}
batteryPercentage
is the variable that I am trying to decrement from 1 to 0 by 0.01 every 9 seconds until the value reaches 0. The total length of the program should be 900 seconds (15 minutes). Every 9 seconds, I want this code to execute every nine seconds and to change the value of the UIProgressView
called batteryLevel
. Then, I want to multiply batteryPercentage
by 100, to get a whole percentage number, such as multiplying 0.67 to get 67, then replace the batteryLevelLabel
text with the new value. When I try and execute this, the batteryLevel
Progress View simply doesn't fill and the text doesn't change. I'm assuming there's something wrong with the timer, so what would be a more effective way of inputing a 9 second delay?
回答1:
try with nstimer as suggested
[NSTimer scheduledTimerWithTimeInterval:9.0
target:self
selector:@selector(targetMethod:)
userInfo:nil
repeats:YES];
//targetMethod will be called every 9 second
//call
[myTimer invalidate]; myTimer = nil;
when your task is done
回答2:
Here's a way to do it that keeps close to your existing structure using NSThread:
@interface MyThread : NSThread
@end
@implementation MyThread
-(void)main
{
NSDate * when = [ NSDate date ] ;
for ( int battery = 1000; battery >= 0; battery -= 1 )
{
when = [ NSDate dateWithTimeInterval:1.0 sinceDate:when ] ;
[ NSThread sleepUntilDate:when ] ;
[ [ NSThread mainThread ] perform:^{
[batteryLevel setProgress:(CGFloat)battery / 10.0 animated:YES];
batteryLevelLabel.text = [NSString stringWithFormat:@"Battery Level: %f%%", (CGFloat)battery / 10.0 ];
}];
}
}
@end
helper category:
@implementation NSThread (Perform)
-(void)_perform:(void(^)())block
{
block() ;
}
-(void)perform:(void(^)())block
{
BOOL wait = [ NSThread currentThread ] == self ;
[ self performSelector:@selector( _perform: ) onThread:self withObject:[ block copy ] waitUntilDone:wait ] ;
}
@end
Then start your timer with NSThread * thread = [ [ MyThread alloc ] init ] ; [ thread start ] ;
Probably easier to just rework your app to use a standard NSTimer + callback structure...
(I also did one using GCD to see what it looks like:
dispatch_queue_t q = dispatch_queue_create( NULL, NULL ) ;
dispatch_async( q, ^{
NSDate * when = [ NSDate date ] ;
for ( int battery = 1000; battery >= 0; battery -= 1 )
{
dispatch_sync( dispatch_get_main_queue(), ^{
[batteryLevel setProgress:(CGFloat)battery / 10.0 animated:YES];
batteryLevelLabel.text = [NSString stringWithFormat:@"Battery Level: %f%%", (CGFloat)battery / 10.0 ];
}) ;
when = [ NSDate dateWithTimeInterval:1.0 sinceDate:when ] ;
[ NSThread sleepUntilDate:when ] ;
}
}) ;
(But I don't think it's guaranteed that different queues are on different threads)
回答3:
You can use + (void)sleepUntilDate:(NSDate *)aDate
!
来源:https://stackoverflow.com/questions/21801509/objective-c-time-delay