Check time difference between method calls objective-c - objective-c

I have this method:
- (void) receivedData {
}
This should run about every 50 to 100 milliseconds. Is there a way to check the time since the last time it was called and print the last time to an NSString?

#interface MyClass() {
NSDate* receivedDataTimestamp;
....
}
...
-(void)receivedData {
NSDate* now = [NSDate date];
if (receivedDataTimestamp != nil) {
NSTimeInterval delta = [now timeIntervalSinceDate:receivedDataTimestamp];
NSLog(#"%f seconds since recevedData was called last", delta);
}
receivedDataTimestamp = now;
....
}

Related

Why NSMutableDictionary's setValue:forKey doesn't work

I want to write a timer class that records average elapsed time of a function. So I want to save how many times the function is ran. But the item in dictionary isn't changed.
here is my code:
#implementation Timer {
NSDate *startTime;
// NSString *item;
NSMutableDictionary *itemCounts;
NSMutableDictionary *itemTimes;
}
- (void)tic {
startTime = [NSDate date];
}
- (void)tocWithMessage:(NSString*)message {
if (itemCounts[message] == nil) {
// itemCounts[message] = #1;
[itemCounts setValue:#1 forKey:message];
NSLog(#"%d", [itemCounts[message] integerValue]);
} else {
itemCounts[message] = #([itemCounts[message] integerValue] + 1);
}
double totalTime = [itemTimes[message] doubleValue];
double thisTime = -[startTime timeIntervalSinceNow] * 1000;
totalTime += thisTime;
itemTimes[message] = #(totalTime);
int count = [itemCounts[message] integerValue];
double averageTime = totalTime / count;
NSLog(#"%#: No.%d, average time: %lfms", message, count, averageTime);
// std::cout << message << ": " << 1. * (clock() - timerTimestamp) / CLOCKS_PER_SEC * 1000 << "ms" << std::endl;
}
#end
But the itemCounts[message] is always nil. Please help me :)
Thanks in advance!
You forgot to initialize the dictionaries. In Swift you would have seen a crash if you do like this :)
You have only declared the dictionaries.
Before using them you have to initialize them somewhere:
itemCounts = [[NSMutableDictionary alloc] init];
itemTimes = [[NSMutableDictionary alloc] init];

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];

Calculating with time and getting a status

I hope you can help me with this:
I´m writing a App that should show if a shop has actually open.
For this i declared for each day and each opening times different variables / NSDate-Objects like (setting the dateformatter I´ve done before):
NSDate *mondayMorningOpening = [dateFormatter dateFromString:#"08:00"];
NSDate *montagMorningClosing = [dateFormatter dateFromString:#"12:30"];
NSDate *mondayNoonOpening = [dateFormatter dateFromString:#"15:00"];
NSDate *montagNoonClosing = [dateFormatter dateFromString:#"21:30"];
I´ve also set a NSDate for the actual time:
NSString *tempDate1 = [dateFormatter stringFromDate:date];
NSDate *actualTime = [dateFormatter dateFromString:tempDate1];
Now I want to calculate if the actual time is before or after the time range for the opening times of the shop. I´ve done this:
if ([actualTime earlierDate: mondayMorningClosing && [aktuelleZeit laterDate: mondayMorningOpening])
{
NSLog (#"The shop is open!");
}
else if ([actualTime earlierDate: mondayNoonClosing]&& [actualTime laterDate: mondayNoonOpening])
{
NSLog (#"The shop is open!");
}
else
{
NSLog (#"The shop is closed!");
}
But no matter what time it is, it´s always shown "The shop is open!".
Maybe you have an idea what to do that i can show the opening status right...
You misunderstood the meaning of earlierDate and laterDate.The methods are not "isEarlierDate" and "isLaterDate", they do not return a BOOL.These methods return a NSDate object, the earlier (or later) of the two dates.They're not nil objects, so they're always evaluated to true.
Compare the two dates taking it's time interval:
if ([actualTime timeIntervalSinceDate: mondayMorningClosing]<0 && [aktuelleZeit timeIntervalSinceDate: mondayMorningOpening]>0)
{
NSLog (#"The shop is open!");
}
You can compare two dates, but as a result you will have a NSDate:
if ([date1 compare:date2] == NSOrderedDescending) {
NSLog(#"date1 is later than date2");
} else if ([date1 compare:date2] == NSOrderedAscending) {
NSLog(#"date1 is earlier than date2");
}
If you have 2 dates you can determine if an NSDate is between those two like this:
- (BOOL)isDate:(NSDate *)date betweenFirstDate:(NSDate *)firstDate andSecondDate:(NSDate *)secondDate
{
BOOL isEqualToFirstOrSecond = [date compare:firstDate] == NSOrderedSame || [date compare:secondDate] == NSOrderedSame;
BOOL isBetweenFirstAndSecond = [date compare:firstDate] == NSOrderedDescending && [date compare:secondDate] == NSOrderedAscending;
return isEqualToFirstOrSecond || isBetweenFirstAndSecond;
}

ios how to change an image at specific time

I have an image that i want to display as a sun during daytime i.e. from 6am to 6pm, and moon from 6pm to 6am.
I have successfully implemented that but the problem is the image would not change when it reaches the specified time unless re-run the apps before the image change itself.
I don't want to use NSTimer to check the time, like every second. The only possible solution i think of is using NSLocalNotification but I'm a newbiew to it. any help? =)
-(void) dayOrNight
{
NSDate* date = [NSDate date];
NSDateFormatter* dateFormat = [[NSDateFormatter alloc]init];
[dateFormat setDateFormat:#"HHmm"];
NSString* dateString = [dateFormat stringFromDate:date];
NSNumber* currentTime = [NSNumber numberWithInt:[dateString intValue]];
NSNumber* daytime = [NSNumber numberWithInt:600];
NSNumber* nightime = [NSNumber numberWithInt:1800];
NSLog(#"current time: %#",dateString);
dayNight = [[UIImageView alloc] initWithFrame:CGRectMake(265, 10, 50, 50)];
if ( [currentTime doubleValue] >= [daytime doubleValue] && [currentTime doubleValue] <= [nightime doubleValue] )
{
dayNight.image = [UIImage imageNamed:#"Sun.png"];
}
else
{
dayNight.image = [UIImage imageNamed:#"moon.png"];
}
[self.view addSubview:dayNight];
}
Local notification should be fine, I guess.
Here you can get all needed code snippets to implement execution of dayOrNight method at needed time. Also, you shouldn't add new view every time you change the picture.
I think it is impossible to do without NSTimer. U can set refreshTime by yourself (for example 1 min/ if u don`t want to do it every second)))
Or u can call this method in other methods, which are working in your class every time...
maybe u have some object, which u use during your class is working...
-(IBAction)myButtonWhichIPressDuringIworkHere {
///some actions
[self dayOrNight];
}
In other case you should to use NSTimer
you don't need to check the time at every second.
this is one of the possible solutions. it has been tested on real device only.
your UIYourViewController.m
- (void)viewWillAppear:(BOOL)animated {
NSDate *_currentDate = [NSDate date];
NSDateFormatter *_dateFormatter = [[NSDateFormatter alloc] init];
[_dateFormatter setDateFormat:#"yyyy-MM-dd' 06:00AM +0000'"]; // set the morning date here
NSString *_morningDateString = [_dateFormatter stringFromDate:_currentDate];
[_dateFormatter setDateFormat:#"yyyy-MM-dd' 06:00PM +0000'"]; // set the evening date here
NSString *_eveningDateString = [_dateFormatter stringFromDate:_currentDate];
[_dateFormatter setDateFormat:#"yyyy-MM-dd hh:mma zzz"];
NSDate *_morningDate = [_dateFormatter dateFromString:_morningDateString];
NSDate *_eveningDate = [_dateFormatter dateFromString:_eveningDateString];
NSTimeInterval _intervalToMorningDate = [_morningDate timeIntervalSinceDate:_currentDate];
NSTimeInterval _intervalToEveningDate = [_eveningDate timeIntervalSinceDate:_currentDate];
if (_intervalToMorningDate > 0) {
// now it is night
dayNight.image = [UIImage imageNamed:#"moon.png"];
[self performSelector:#selector(replaceTheBackgoundForMorning) withObject:nil afterDelay:_intervalToMorningDate];
} else {
// now it is daytime
dayNight.image = [UIImage imageNamed:#"Sun.png"];
[self performSelector:#selector(replaceTheBackgoundForEvening) withObject:nil afterDelay:_intervalToEveningDate];
}
}
- (void)viewDidDisappear:(BOOL)animated {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
and finally you should add them to your same .m file:
-(void)replaceTheBackgoundForMorning {
// reaplce the backgound here
dayNight.image = [UIImage imageNamed:#"Sun.png"];
}
- (void)replaceTheBackgoundForEvening {
// reaplce the backgoung here
dayNight.image = [UIImage imageNamed:#"moon.png"];
}

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.