How to scan array by time - iphone

I have an array and every object of the array is with 2 objects:
double = time in miliseconds
nsstring = string to print
and i want that my app will scan the array and when it will come to the time of the miliseconds it will print the nsstring.

Alright, I assume the objects are called MyObject, and the array is called objectArray, so try this:
- (void)checkArrayForTimes; {
float epsilon = 0.1;
NSDate * currentTime = [NSDate date];
float milliseconds = [currentTime timeIntervalSinceDate:startTime];
milliseconds -= (int)milliseconds; // This mods out all of the seconds so you are only working with milliseconds.
for(MyObject * myObject in objectArray){
if(fabs(myObject.time - milliseconds) < epsilon){
NSLog(#"%#", myObject.string);
}
}
}
In your .h file, add the line:
NSDate * startDate;
Then, in your viewDidLoad: method, add the lines:
// Note, you can change the 0.05 to fit your needs.
startDate = [[NSDate date] retain];
[NSTimer scheduledTimerWithTimeInterval:0.05 target:self selector:#selector(checkArrayForTimes) userInfo:nil repeats:YES];
(Note:, you may need to use a NSDateFormatter to get an NSDate with 0 milliseconds.) Finally, in your dealloc method, add:
[startDate release];
Hope that Helps!

Related

why am i getting negative values for my timeinterval?

I have no idea what is happening. I am trying to make a timer that works by comparing dates. When I start the timer, sometimes it works and then randomly stops, and sometimes it just returns the value of the timeInterval. It seems to only work correctly when the time interval is negative. This is my method:
-(IBAction)startTimer:(id)sender{
if (timer == nil) {
[startButton setTitle:#"Start" forState:UIControlStateNormal];
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerAction:) userInfo:nil repeats:YES];
date = [NSDate dateWithTimeIntervalSinceNow:testTask.timeInterval]; //instance variable
} else {
[startButton setTitle:#"Stop" forState:UIControlStateNormal];
[timer invalidate];
timer = nil;
}
}
-(void)timerAction:(NSTimer *)t
{
NSDate *currentDate = [NSDate date];
NSTimeInterval updatedTimeInterval = [date timeIntervalSinceDate:currentDate];
if (updatedTimeInterval > 0){
if (self.timer)
{
[self timerExpired];
[self.timer invalidate];
self.timer = nil;
}
}
else
{
testTask.timeInterval = updatedTimeInterval;
NSLog(#"%.2f", testTask.timeInterval);
NSError *error;
if (![self.context save:&error]) {
NSLog(#"couldn't save: %#", [error localizedDescription]);
}
}
NSUInteger seconds = (NSUInteger)round(testTask.timeInterval);
NSString *string = [NSString stringWithFormat:#"%02u:%02u:%02u",
seconds / 3600, (seconds / 60) % 60, seconds % 60];
timerLabel.text = string;
NSLog(#"%f", testTask.timeInterval);
}
You're subtracting the later date, currentDate, from the earlier date. I told you to do it the other way around: [[NSDate date] timeIntervalSinceDate:date]
There's a reason timeIntervalSinceNow is not called timeIntervalUntilNow...
Also known as: the time elapsed since now is negative if the date in question is earlier than the current date/time. It would be positive if the date was later in time than the current date. (Just a bit of logic and/or English semantics :))
Earlier date Current date
^ ^
+------------------+
since now: (earlier date) - (current date)... that's < 0

NSTimer crashes with bad access

I have the following method to update a label which show a simple time up
-(void)updateTimeLabel:(NSTimer *)timer{
NSInteger secondsSinceStart = (NSInteger)[[NSDate date] timeIntervalSinceDate:_startTime];
NSInteger seconds = secondsSinceStart % 60;
NSInteger minutes = (secondsSinceStart / 60) % 60;
NSInteger hours = secondsSinceStart / (60 * 60);
NSString *result = nil;
if (hours > 0) {
result = [NSString stringWithFormat:#"%02d:%02d:%02d", hours, minutes, seconds];
}
else {
result = [NSString stringWithFormat:#"%02d:%02d", minutes, seconds];
}
_totalTime = result;
_totalTimeLabel.text = result;
}
I then call this as the action to a button:
-(IBAction) startTimer{
_startTime = [NSDate date];
_walkRouteTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimeLabel:) userInfo:nil repeats:YES];
[_walkRouteTimer fire];
}
But when I run the app I get a bad access error and the app crashes, can anyone help me with this?
Thanks in advance
Are you using ARC? If not, _startTime = [NSDate date]; this line will cause your problem. [NSDate date] returned an autorelease object and _startTime will not hold it if you are not using ARC(or using ARC but declared _startTime as weak).
If so, try to add a retain to it
-(IBAction) startTimer{
//_startTime = [NSDate date]
_startTime = [[NSDate date] retain];
_walkRouteTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimeLabel:) userInfo:nil repeats:YES];
[_walkRouteTimer fire];
}
And when you finished your timer, after calling of [_walkRouteTimer invalidate], call [_startTime release].
Or even simpler, if you use property for startTime and declared it as retain. Just use dot notation:
-(IBAction) startTimer{
//_startTime = [NSDate date]
self.startTime = [NSDate date];
_walkRouteTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(updateTimeLabel:) userInfo:nil repeats:YES];
[_walkRouteTimer fire];
}
...
//After [_walkRouteTimer invalidate]
self.startTime = nil;
Try adding an exception breakpoint to see which line is crashing:
1) Click on the breakpoint tab (second from the right)... kinda looks like a right pointing arrow or "next" button
2) Click on the "+" in the bottom left corner of the tab menu
3) Select "Add Exception Breakpoint"
4) (Optional) Select "Exception" drop down and change to "Objective-C"
5) Select "Done"
6) Run your code again and try to generate the crash... when you do, it will hopefully be caught by this breakpoint, and you'll see which line is crashing and be able to fix it
Good luck

Create a count up timer with support for hours, mins seconds, split seconds iPhone sdk

Interested in creating a timer to count up for the user.
I was wondering if I'd have to keep track of all the integer variables separately or if I could use date formatter.
I'm currently using a -scheduledTimerfoo to call an -updateLabel method with seconds, but It looks a bit horrible after 100 seconds. I'd sort of like "hours:mins:seconds:split seconds" to display.
Cheers
Sam
NSDateFormatter is only for formatting dates, not intervals of time. A better way to do this would be to record when you start the timer, and every second, update the label with how much time passed since you started the timer.
- (void)startTimer {
// Initialize timer, with the start date as the userInfo
repeatTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:#selector(updateLabel) userInfo:[NSDate date] repeats:YES];
}
- (void)updateLabel:(NSTimer *)timer {
// Get the start date, and the time that has passed since
NSDate *startDate = (NSDate *)[timer userInfo];
NSTimeInterval timePassed = [[NSDate date] timeIntervalSinceDate:startDate];
// Convert interval in seconds to hours, minutes and seconds
int hours = timePassed / (60 * 60);
int minutes = ((int)timePassed % (60 * 60)) / 60;
int seconds = (((int)timePassed % (60 * 60)) % 60);
NSString *time = [NSString stringWithFormat:#"%i:%i:%i", hours, minutes, seconds];
// Update the label with time string
}

How do I measure the time interval from a starting point using NSDate?

I have one method that I use in many places throughout my project that looks like the following:
-(void)showSignInView
{
if(check for time interval)
[[self superview] addSubview:loginController.view];
}
I'd like to note the first time that this method is called, then on every subsequent call of this method check to make sure that the interval has been more than 15 minutes from the original call. Only then will it execute the rest of its code.
I know that you can use NSDate to measure time intervals using code like the following:
NSDate *firstTime = [[NSDate date] retain];
NSDate *SecondTime = [NSDate date];
NSLog(#"Time elapsed: %f", [SecondTime timeIntervalSinceDate:firstTime]);
but I'm not sure how to implement the initial time check, then subsequent comparisons to that time. How can I do this?
Create a property named previousTime.
#property(nonatomic, retain) NSDate *previousTime;
And create a method to find the time difference.
- (NSTimeInterval)timeDifferenceSinceLastOpen {
if (!previousTime) self.previousTime = [NSDate date];
NSDate *currentTime = [NSDate date];
NSTimeInterval timeDifference = [currentTime timeIntervalSinceDate:previousTime];
self.previousTime = currentTime;
return timeDifference;
}
You could use GCD to achieve this. The dispatch_once() function can arrange that a block is only executed once in the lifetime of your app.
NSDate *firstTime = nil;
- (void)loadView {
[self calculateTime:[NSDate dateWithTimeIntervalSince1970:1312996898]];
}
- (void)calculateTime:(NSDate*)secondTime
{
double offset = [secondTime timeIntervalSinceDate:[self getFirstTime]];
if (offset >= 900.0) {
NSLog(#"15 min gone");
}
}
- (NSDate *)getFirstTime
{
if (!firstTime) {
firstTime = [[NSDate date] retain];
}
return firstTime;
}

how to pause and resume NSTimer in iphone

hello
I am developing small gameApp.
I need to pause the timer,when user goes to another view [say settings view].
when user comes back to that view , I need to resume the timer.
can anybody solve this issue ...
Thanks in Advance...
NSTimer does not give you the ability to pause it. However, with a few simple variables, you can create the effect yourself:
NSTimer *timer;
double timerInterval = 10.0;
double timerElapsed = 0.0;
NSDate *timerStarted;
-(void) startTimer {
timer = [NSTimer scheduledTimerWithTimeInterval:(timerInterval - timerElapsed) target:self selector:#selector(fired) userInfo:nil repeats:NO];
timerStarted = [NSDate date];
}
-(void) fired {
[timer invalidate];
timer = nil;
timerElapsed = 0.0;
[self startTimer];
// react to timer event here
}
-(void) pauseTimer {
[timer invalidate];
timer = nil;
timerElapsed = [[NSDate date] timeIntervalSinceDate:timerStarted];
}
This has been working out quite well for me.
You can't pause a timer. However, when the user goes to the settings view, you can save the fireDate of the timer and also the current date. After this you invalidate the timer and let the user do his/her stuff.
Once he/she switches back to the game, you create a new timer object and set the fire date to the old fire date plus the time the user was in the menu (oldTime + currentTime).
you can use this code to implement pause and resume functionality in NSTimer
//=========new timer update method=============
-(void) updateTimer {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss.S"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString = [dateFormatter stringFromDate:timerDate];
lblMessage.text = timeString;
pauseTimeInterval = timeInterval;
}
-(IBAction) startBtnPressed:(id)sender
{
//=============================new update with start pause==================
if(running == NO) {
running = YES;
startDate = [NSDate date] ;
startDate = [[startDate dateByAddingTimeInterval:((-1)*(pauseTimeInterval))] retain];
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0 target:self selector:#selector(updateTimer) userInfo:nil repeats:YES];
}
else {
running = NO;
[stopWatchTimer invalidate];
stopWatchTimer = nil;
[self updateTimer];
}
}
declare in .h file NSDate startDate;
NSTimeInterval pauseTimeinterval;
and in viewdidload pausetimeInterval=0.0; good luck
You can't pause an NSTimer. You can, however invalidate it and create a new one when needed.
on Start -
startNewCapture = [NSDate date];
on Pause -
captureSessionPauseDate = [NSDate date];
captureSessionTimeInterval = [captureSessionPauseDate timeIntervalSinceDate:startNewCapture];
on Resume -
NSDate *dateNow = [NSDate date];
startNewCapture = [NSDate dateWithTimeInterval:-captureSessionTimeInterval sinceDate:dateNow];
- (IBAction)pauseResumeTimer:(id)sender {
if (timerRunning == NO) {
timerRunning = YES;
[pauseTimerBtn setTitle:#"Resume" forState:UIControlStateNormal];
NSString *stringVal = [NSString stringWithFormat:#"%#",timeTxt.text];
stringVal = [stringVal stringByReplacingOccurrencesOfString:#":" withString:#"."];
float tempFloatVal = [stringVal floatValue];
int minuteValue = floorf(tempFloatVal);
float tempSecVal = [stringVal floatValue] - floorf(tempFloatVal);
int secondVal = tempSecVal*100;
minuteValue = minuteValue*60;
oldTimeValue = minuteValue + secondVal;
[timer invalidate];
timer = nil;
}
else
{
timerRunning = NO;
[pauseTimerBtn setTitle:#"Pause" forState:UIControlStateNormal];
startDate = [NSDate date];
timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(timer:) userInfo:nil repeats:YES];
}
}
- (void)runTimer:(NSTimer *)timer {
NSInteger secondsAtStart = (NSInteger)[[NSDate date] timeIntervalSinceDate:startDate];
secondsAtStart = secondsAtStart + oldTimeValue;
NSInteger seconds = secondsAtStart % 60;
NSInteger minutes = (secondsAtStart / 60) % 60;
NSInteger hours = secondsAtStart / (60 * 60);
NSString *result = nil;
result = [NSString stringWithFormat:#"%02ld:%02ld",(long)minutes,(long)seconds];
timeTxt.text = result;
}
Did you end up figuring it out? I saw that you said that you cannot invalidate your timer when you go into another view. Can you explain what you mean by that? NSTimers cannot be paused, and methods to simulate pausing them usually involve invalidating them. You can then simulate "unpausing" by creating a new timer that will then start up again. This will simulate a timer being paused and unpaused.
For people who would like a potentially more convenient method, I wrote a controller class that can conveniently handle pausing and unpausing timers. You can find it here: https://github.com/LianaChu/LCPausableTimer
You can use the controller class that I wrote to create new timers, and then you can pause and unpause the timers by call the methods "pauseTimer" and "unpauseTimer" on the controller class.
I would greatly appreciate any comments or feedback like how you used it, what changes you would like to see, or any features you would like me to add. Please don't hesitate to reply with your comments here, or post on the issues tab on the Github page.