I need to create a Timer that counts down from a string I get from the server. the string outputs total seconds left.
I am using this code - it calculates the initial number time right and it counts down but the minutes are the problem.
EDIT - Every real minute the minute calculation goes up by one. But I don't understand why it is doing this.
-(void)showTimmer:(id) sender {
//get total amount of seconds
NSString *timeRaw = [ArrayFromServer objectAtIndex:1];
NSArray *timeArr = [timeRaw componentsSeparatedByString:@","];
timetoInt = [timeArr objectAtIndex:0];
int time1 = [timetoInt intValue];
//set the second countdown
NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [gregorian components:(NSSecondCalendarUnit) fromDate:now];
NSInteger seconds = time1 - [dateComponents second];
[gregorian release];
// do the hours days maths
int hour = (seconds / 3600 );
seconds -= hour * 3600开发者_StackOverflow;
int minute = (seconds / 60 );
seconds -= minute * 60;
int second = seconds;
//set the labels
countdownLabel.text = [NSString stringWithFormat:@"%02dH %02dM %02ds", hour, minute, second];
You need to subtract the calculated hours from the total amount of seconds before going to the next line (not sure why you use modulo). Something like this (note
int hour = (seconds / 3600 );
seconds -= hour * 3600;
int minute = (seconds / 60 );
seconds -= minute * 60;
int second = seconds;
Hope that fixes it.
You're using your pliers to drive a screw. The seconds
method of an NSDateComponents
gives you what you would see on a clock if you looked at the second hand at the time represented by your NSDate
. For example, as I type this, it's UTC Saturday March 26, 2011, 02:52:04. If I got [NSDate date]
, turned it into an NSDateComponents
and asked that for its seconds
, I'd get "4". If I did it again in a second, I'd get "5", and when the minute clicked over, I'd get "59", then "0".
You can verify this for yourself; put this in your timer method:
NSInteger dcSecond = [dateComponents second];
NSLog(@"%d", dcSecond);
So every time the minute of the actual clock ticks over, your calculation of the remaining time:
NSInteger seconds = time1 - [dateComponents second];
subtracts 0
from time1
and gives you back time1
. That's why you're having the problem.
The way* to fix it is to dump the calendar stuff and use CFAbsoluteTimeGetCurrent()
. First, put the start time in your timer's userInfo (or in an ivar if you prefer):
[NSTimer scheduledTimer...
// The function returns CFAbsoluteTime, which is a
// typedef'd double but you're already working with
// integers, so use a cast
userInfo:[NSNumber numberWithInteger:(NSInteger)CFAbsoluteTimeGetCurrent()]
...];
Then change your calculation of the remaining time (the variable you call seconds
:
NSInteger startTime = [[timer userInfo] integerValue];
NSInteger currTime = (NSInteger)CFAbsoluteTimeGetCurrent();
NSInteger elapsedTime = currTime - startTime;
NSInteger duration = time1 - startTime;
//NSInteger seconds = time1 - [dateComponents second];
NSInteger remaining = duration - elapsedTime;
int hour = remaining / 3600;
...
*: Well, one way, but I think probably the best.
精彩评论