iOS timeout functionality not working properly - objective-c

I added this code which functions as an auto timeout in my app. The userDefaults doubleForKey:#"timeoutLength" should be in minutes. For example, if value is 500, that should mean 500 minutes.
I keep seeming to be hitting the timout loop though even when it hasn't really been 500 + min. Is anything wrong in my code? Perhaps a minutes/seconds error etc.
[userDefaults setDouble:[[userContextDictionary valueForKey:#"autologout_idle_timeout"] doubleValue] forKey:#"timeoutLength"];
double timeDifference = ([[NSDate date] timeIntervalSince1970] - [userDefaults doubleForKey:#"Close Time"]) / 60;
if (timeDifference > [userDefaults doubleForKey:#"timeoutLength"]) {
NSLog(#"Timeout Hit");
} else {
NSLog(#"No Timeout");
}
Edit:
- (void)applicationDidEnterBackground:(UIApplication *)application {
[userDefaults setObject:[NSDate date] forKey:#"Close Time"];
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[userDefaults setDouble:[[userContextDictionary valueForKey:#"autologout_idle_timeout"] doubleValue] forKey:#"timeoutLength"];
//This is an int like 500, or 600, etc.
NSDate *closeDate = [userDefaults objectForKey:#"Close Time"]
NSTimeInterval timeWhenClosedTimeInterval = [closeDate timeIntervalSince1970];
NSTimeInterval todayTimeInterval = [[NSDate date] timeIntervalSince1970];
NSTimeInterval timeDifference = ((todayTimeInterval - timeWhenClosedTimeInterval ) / 60);
if (timeDifference > [userDefaults doubleForKey:#"timeoutLength"]) {
NSLog(#"Timeout Hit");
} else {
NSLog(#"No Timeout");
}
return YES;
}

NSTimeInterval is expressed in seconds, not minutes.
Here's the Apple doc where it's described.
I'm not 100% certain what your ultimate problem with, but 500 seconds doesn't seem like nearly enough time.
In the meantime, I wrote up some changes to your code to demo for myself:
NSDate * yesterday = [[NSDate date] dateByAddingTimeInterval: (-1 * 60 * 60 * 24 )];
NSTimeInterval yesterdayTimeInterval = [yesterday timeIntervalSince1970];
NSTimeInterval todayTimeInterval = [[NSDate date] timeIntervalSince1970];
// this properly converts timeDifference in seconds to minutes
NSTimeInterval timeDifference = ((todayTimeInterval - yesterdayTimeInterval ) / 60);
NSLog( #"time difference is %4.2f", timeDifference );
which came up with 1400 minutes (divided by 60 minutes per hour = 24 hours).

My guess is there is some error with setting the NSUserDefaults values, or an error with your timeDifference calculation. Add this line and make sure you are actually setting the timeout length to 500:
NSLog(#"Timeout length: %f, close time: %f, time difference: %f", [userDefaults doubleForKey:#"timeoutLength"], [userDefaults doubleForKey:#"Close Time"], timeDifference);

Related

Convert UIEvent timestamp to UNIX date

I use touchbegin function like
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
touchStartTime = [event timestamp];
NSLog(#"Time of touch is %f ", touchStartTime);
}
but I would like to compare it with
double timeToCompare = [[NSDate date] timeIntervalSince1970];
but the format is not compatible (timestamp has some other reference point). How do I convert [event timestamp] to normal NSDate or vice versa?
As [event timestamp] is related to the system up time, you can get the [NSProcessInfo systemUptime] and get the current system time at the same time and go from there.
[[NSDate date] timeIntervalSince1970] - [NSProcessInfo systemUptime] + [event timestamp] == [compareDate timeIntervalSince1970]
(Well, I don't sign this in blood. Never tried it myself.)
Given that [UIEvent timestamp] is the number of seconds since the system was started, one approach to record the first event's timestamp and use that as a reference.
#interface MyClass ()
{
BOOL _haveFirstTimestamp;
NSTimeInterval _firstTimestamp;
NSTimeInterval _firstTimestampTime;
}
#end
...
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
{
NSTimeInterval timestamp = [event timestamp];
if (!_haveFirstTimestamp) {
_haveFirstTimestamp = YES;
_firstTimestamp = timestamp;
_firstTimestampTime = [[NSDate date] timeIntervalSince1970];
}
NSTimestamp timeSince1970 = timestamp - _firstTimestamp + _firstTimestampTime;
NSLog(#"Time of touch is %f ", timeSince1970);
}

Having milliseconds in my timer in Objective-C

I'm doing a stopwatch using a youtube tutorial. The problem is that I want milliseconds in my timer but the tutorial only shows how to get seconds and minutes. I would like to get the milliseconds displayed like the minutes and seconds, but I've got no idea how to do it.
How to get milliseconds using this code?
#implementation ViewController {
bool start;
NSTimeInterval time;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.display.text = #"0:00";
start = false;
}
- (void) update {
if ( start == false ) {
return;
}
NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate];
NSTimeInterval elapsedTime = currentTime - time;
int minutes = (int) (elapsedTime / 60.0);
int seconds = (int) (elapsedTime = elapsedTime - (minutes * 60));
self.display.text = [NSString stringWithFormat:#"%u:%02u", minutes, seconds];
[self performSelector:#selector(update) withObject:self afterDelay:0.1];
}
According to the docs, "NSTimeInterval is always specified in seconds; it yields sub-millisecond precision over a range of 10,000 years." So all you need to do is extract the milliseconds from your elapsedTime variable and then format your text again so that it includes milliseconds. It might looks something like this:
NSInteger time = (NSInteger)elapsedTime;
NSInteger milliseconds = (NSInteger)((elapsedTime % 1) * 1000);
NSInteger seconds = time % 60;
NSInteger minutes = (time / 60) % 60;
//if you wanted hours, you could do that as well
//NSInteger hours = (time / 3600);
self.display.text = [NSString stringWithFormat: "%ld:%ld.%ld", (long)minutes, (long)seconds, (long)milliseconds];

NSDate countdown from NOW to NSDate

How can I show a countdown in HH:mm:ss format from NOW to a desired NSDate that will happen in the future?
Start at the documentation.
NSDate *future = // whatever
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateCounter:) userInfo:nil repeats:YES];
- (void)updateCounter:(NSTimer *)tmr
{
NSTimeInterval iv = [future timeIntervalSinceNow];
int h = iv / 3600;
int m = (iv - h * 3600) / 60;
int s = iv - h * 3600 - m * 60;
aUILabel.text = [NSString stringWithFormat:#"%02d:%02d:%02d", h, m, s];
if (h + m + s <= 0) {
[tmr invalidate];
}
}
You have to use a timer for ticking the date.
Store a future date, and keep on substracting future date - [nsdate today]...
Calculate the time in seconds and calculate it into Hours, minutes, seconds...
//Make two properties NSDate *nowDate, *futureDate
futureDate=...;
nowDate=[NSDate date];
long elapsedSeconds=[nowDate timeIntervalSinceDate:futureDate];
NSLog(#"Elaped seconds:%ld seconds",elapsedSeconds);
NSInteger seconds = elapsedSeconds % 60;
NSInteger minutes = (elapsedSeconds / 60) % 60;
NSInteger hours = elapsedSeconds / (60 * 60);
NSString *result= [NSString stringWithFormat:#"%02ld:%02ld:%02ld", hours, minutes, seconds];
This will come handy for you...kindly check the project...
Give this code a shot:
NSTimer* timer= [NSTimer scheduledTimerWithInterval: [self.futureDate timeIntervalSinceNow] target: self selector: #selector(countdown:) userInfo: nil, repeats: YES];
The countdown: method:
- (void) countdown: (NSTimer*) timer
{
if( [self.futureDate timeIntervalSinceNow] <= 0)
{
[timer invalidate];
return;
}
NSDateComponents* comp= [ [NSCalendar currentCalendar] components: NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit startingDate: [NSDate date] toDate: self.futureDate options: 0];
NSLog(#"%lu:%lu:%lu", comp.hour,comp.minute.comp.second);
}

TimeInterval calculation issue

I am trying to create an app that calculates the time difference and the amount is multiplied by an amount in money. It is targeted to calculate in R$ (brazilian real) the amount that someone will have to pay for using a service during the time calculated by the app.
Here´s is my code:
- (IBAction)encerrar:(id)sender {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
dateFormatter.dateFormat = #"HH:mm";
NSString *temp = inicio.text;
NSDate *then = [dateFormatter dateFromString:temp];
NSDate *now = [NSDate date];
NSTimeInterval timeInterval = [now timeIntervalSinceDate:then];
NSString *ext = [dateFormatter stringFromDate:now];
fim.text = ext;
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
duracao.text = timeString;
double timeIntervalInHours = (timeInterval / 3600.0) * 5;
NSString *vTotal = [[NSString alloc] initWithFormat:#"R$ %.2f", fecha];
NSLog(#"%.2f", timeIntervalInHours);
vlrTotal.text = vTotal;
}
The fact is that when we click on Calculate button, and if the duracao (duration) is equal to 1h it gives me the correct amount which is R$ 5,00. But when the duration is equal to 30mins or other value different from exact 1h, it gives the wrong amount.
I.E.: 1h should be R$ 5,00; while 1:30h should be R$ 7,50, but shows me R$ 6,50.
So, anyone could help me on this???
Thanks in advance!!!
timeInterval is the amount of time in seconds, so if you want it in hours and fractions of an hour just do this:
double timeIntervalInHours = timeInterval / 3600.0;
and then multiple timeIntervalInHours times the price/hour to get the cost.
EDIT
Based on our chat, I would create a button with "iniciar" (start) as the title. When they press that button, I would store the current time and change the title to "encerrar" (stop). (I hope that my translations are correct, lol) Then the button action would look something like this:
// self.startTime is a NSDate.
- (IBAction)iniciar_encerrar:(UIButton *)sender {
if ([sender.titleLabel.text isEqualToString:#"iniciar"]) {
// We are starting the time
if (self.startTime != nil) {
return;
}
self.startTime = [NSDate date];
[sender setTitle:#"encerrar" forState:UIControlStateNormal];
} else {
// We are stopping the time
NSDate *currentTime = [NSDate date];
NSTimeInterval elapsedTimeInSeconds = [currentTime timeIntervalSinceDate:self.startTime];
double cost = elapsedTimeInSeconds / 3600.0 * 5.0;
NSLog(#"%.2lf", cost);
// reset the button
self.startTime = nil;
[sender setTitle:#"iniciar" forState:UIControlStateNormal];
}
}
startTime is declared as follows:
In your .h file, along with the other declared properties, add:
#property (strong, nonatomic) NSDate *startTime;
In your .m file, add this at the top with the other ones:
#synthesize startTime;
In your viewDidUnload function (in your .m file) add this:
startTime = nil;
This just gives you a place to store the startTime date.
You're converting the time string HHmm to a float, so at 1.5 hours, you will have a float of 130 (1 hour 30 min). I can't follow your calculations from there. I think what you want is to have two formatters, one to get minutes, and one for hours, like so:
formatter.dateFormat = #"HH";
float hours = [[formatter stringFromDate:timerDate] intValue] * 1.0;
formatter.dateFormat = #"mm";
hours += [[formatter stringFromDate:timerDate] intValue]/60.0; //convert min to fractional hours and add
I would convert the amount $R5,00 from an hourly amount to an amount per second for better accuracy. 5/ 60 minutes / 60 seconds gives you .00388889 which you would multiply by (duration*1000) to give you your accurate result.

Counting down the days - iPhone Count Down Timer

I’m trying to make a counter which shows the number of days until we leave on a trip to Europe. It’s only about 70 days (as of today) so I don’t believe that I should have to worry about astronomically large numbers or anything, but I really am stumped - I’ve attached the code that some friends have given me, which don’t work either. Trust me when I say I’ve tried everything I can think of - and before anyone bites my head off, which I have seen done on these forums, yes I did look very extensively at the Apple Documentation, however I’m not 100% sure where to start - I’ve tried NSTimer, NSDate and all their subclasses and methods, but there’s nothing that jumps out immediately.
In terms of what I think I should actually be doing, I think I need to somehow assign an integer value for the “day” today/ now/ the current day, which will change dynamically using the [NSDate date] and then the same for the date that we leave. The countdown is just updating when the method gets called again (I can do this using NSTimer if need be) and the value that is displayed on the countdown is the differnce between these two values.
I don’t especially want to have a flashing kind of thing that updates every second until we leave - personally I think that’s tacky, but if anyone knows how then I’d appreciate it for future reference.
I’ve also done an extensive search of google, and I may simply be using the wrong search terms, but I can’t find anything there either.
Any help is greatly appreciated.
Thank you very much.
Michaeljvdw
- (void)countDownMethod {
NSDateComponents *comps = [[NSDateComponents alloc] init];
[comps setDay:startDay];
[comps setMonth:startMonth];
[comps setYear:startYear];
[comps setHour:startHour];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDate *date = [gregorian dateFromComponents:comps];
NSLog(#"%#",date);
[gregorian release];
[comps release];
NSTimeInterval diff = [date timeIntervalSinceNow];
int diffInt = diff;
NSString *days = [NSString stringWithFormat:#"%d",diffInt/86400];
day0.text = #"0";
day1.text = #"0";
day2.text = #"0";
NSLog(#"Days Length: %d",days.length);
if(days.length >= 1){
day2.text = [days substringFromIndex:days.length - 1];
if(days.length >= 2){
day1.text = [days substringWithRange:NSMakeRange(days.length - 2, 1)];
if(days.length >= 3){
day0.text = [days substringWithRange:NSMakeRange(days.length - 3, 1)];
}
}
}
NSString *hours = [NSString stringWithFormat:#"%d",(diffInt%86400)/3600];
hour0.text = #"0";
hour1.text = #"0";
NSLog(#"Hours Length: %d",hours.length);
if(hours.length >= 1){
hour1.text = [hours substringFromIndex:hours.length - 1];
if(hours.length >= 2){
hour0.text = [hours substringWithRange:NSMakeRange(hours.length - 2, 1)];
}
}
NSString *minutes = [NSString stringWithFormat:#"%d",((diffInt%86400)%3600)/60];
minute0.text = #"0";
minute1.text = #"0";
NSLog(#"Minutes Length: %d",minutes.length);
if(minutes.length >= 1){
minute1.text = [minutes substringFromIndex:minutes.length - 1];
if(minutes.length >= 2){
minute0.text = [minutes substringWithRange:NSMakeRange(minutes.length - 2, 1)];
}
}
}
If you know the time in seconds between 2 dates (your NSTimeInterval) then you can easily convert that into a string in the format days:hours:mins:secs as follows.
- (NSString*)secsToDaysHoursMinutesSecondsString:(NSTimeInterval)theSeconds {
div_t r1 = div(theSeconds, 60*60*24);
NSInteger theDays = r1.quot;
NSInteger secsLeftFromDays = r1.rem;
div_t r2 = div(secsLeftFromDays, 60*60);
NSInteger theHours = r2.quot;
NSInteger secsLeftFromHours = r2.rem;
div_t r3 = div(secsLeftFromHours, 60);
NSInteger theMins = r3.quot;
NSInteger theSecs = r3.rem;
NSString* days;
if (theDays < 10) { // make it 2 digits
days = [NSString stringWithFormat:#"0%i", theDays];
} else {
days = [NSString stringWithFormat:#"%i", theDays];
}
NSString* hours;
if (theHours < 10) { // make it 2 digits
hours = [NSString stringWithFormat:#"0%i", theHours];
} else {
hours = [NSString stringWithFormat:#"%i", theHours];
}
NSString* mins;
if (theMins < 10) { // make it 2 digits
mins = [NSString stringWithFormat:#"0%i", theMins];
} else {
mins = [NSString stringWithFormat:#"%i", theMins];
}
NSString* secs;
if (theSecs < 10) { // make it 2 digits
secs = [NSString stringWithFormat:#"0%i", theSecs];
} else {
secs = [NSString stringWithFormat:#"%i", theSecs];
}
return [NSString stringWithFormat:#"%#:%#:%#:%#", days, hours, mins,secs];
}
//Another simple way to get the numbers of days difference to a future day from today.
NSTimeInterval todaysDiff = [todayDate timeIntervalSinceNow];
NSTimeInterval futureDiff = [futureDate timeIntervalSinceNow];
NSTimeInterval dateDiff = futureDiff - todaysDiff;
div_t r1 = div(dateDiff, 60*60*24);
NSInteger theDays = r1.quot;
label.text = [NSString stringWithFormat:#"%i", theDays];