iphone - difference between time(app hiding) and time(app appearing) - iphone

how do i get the date from appEnterBackground and take away from appEnterForeground, then show the difference in a label.
This is my code so far..
**.h**
NSTimeInterval appEnteredBackground;
NSTimeInterval appEnteredForeground;
NSTimeInterval difference;
**.m**
- (void)applicationDidEnterBackground:(UIApplication *)application
{
appEnteredBackground = [NSDate timeIntervalSinceReferenceDate];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
appEnteredForeground = [NSDate timeIntervalSinceReferenceDate];
difference = appEnteredForeground - appEnteredBackground;
NSLog(#"Duration is %#",[NSDate dateWithTimeIntervalSinceReferenceDate: difference]);
NSLog(#"Duration is %#", [NSString stringWithFormat:#"%f", difference]);
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
NSString *time = [NSString stringWithFormat:#"%f", difference]; **//ERROR HERE (variable not used)**
[dateFormatter release];
}
Any help would be fantastic

I think that you do not have errors here. You are correctly calculating the time difference, then you build a string with its "description" but do not use it.
To see if it all works correctly try this before the end of the method:
NSLog(#"Computed time was: %#", time);
You should care about that time variable, since you are not actively using it.

To measure this type of event (or difference of events), you need something with resolution of less than a second. There is a "c" interface to get the machine time, which is the hardware free running "ticks" inside the processor.
You can get really fine timing (milliseconds, microseconds if you believe them) using this StopWatch class.
StopWatch.h
#import <Foundation/Foundation.h>
#interface StopWatch : NSObject
{
uint64_t _start;
uint64_t _stop;
uint64_t _elapsed;
}
-(void) Start;
-(void) Stop;
-(void) StopWithContext:(NSString*) context;
-(double) seconds;
-(NSString*) description;
+(StopWatch*) stopWatch;
-(StopWatch*) init;
#end
StopWatch.m
#import "StopWatch.h"
#include <mach/mach_time.h>
#implementation StopWatch
-(void) Start
{
_stop = 0;
_elapsed = 0;
_start = mach_absolute_time();
}
-(void) Stop
{
_stop = mach_absolute_time();
if(_stop > _start)
{
_elapsed = _stop - _start;
}
else
{
_elapsed = 0;
}
_start = mach_absolute_time();
}
-(void) StopWithContext:(NSString*) context
{
_stop = mach_absolute_time();
if(_stop > _start)
{
_elapsed = _stop - _start;
}
else
{
_elapsed = 0;
}
NSLog([NSString stringWithFormat:#"[%#] Stopped at %f",context,[self seconds]]);
_start = mach_absolute_time();
}
-(double) seconds
{
if(_elapsed > 0)
{
uint64_t elapsedTimeNano = 0;
mach_timebase_info_data_t timeBaseInfo;
mach_timebase_info(&timeBaseInfo);
elapsedTimeNano = _elapsed * timeBaseInfo.numer / timeBaseInfo.denom;
double elapsedSeconds = elapsedTimeNano * 1.0E-9;
return elapsedSeconds;
}
return 0.0;
}
-(NSString*) description
{
return [NSString stringWithFormat:#"%f secs.",[self seconds]];
}
+(StopWatch*) stopWatch
{
StopWatch* obj = [[[StopWatch alloc] init] autorelease];
return obj;
}
-(StopWatch*) init
{
[super init];
return self;
}
#end
The class has a static stopWatch method that returns an autoreleased object.
Once you call start, use the seconds method to get the elapsed time. Call start again to restart it. Or stop to stop it. You can still read the time (call seconds) anytime after calling stop.
Example In A Function (Timing call of execution)
-(void)SomeFunc
{
StopWatch* stopWatch = [StopWatch stopWatch];
[stopWatch Start];
... do stuff
[stopWatch StopWithContext:[NSString stringWithFormat:#"Created %d Records",[records count]]];
}

Related

How to getStats() in WebRTC iOS SDK in Swift?

I am trying to get ICE Candidate Pair Stats in iOS SDK in Swift. I see this specific interface: statsForTrack but I am unsure about how to use it. Has anybody done this before?
you can use stats function in PeerConnection like this:
peerConnection.stats(for: RTCMediaStreamTrack?, statsOutputLevel: .debug, completionHandler: { reports in
// reports here
}
you can set nil for parameter RTCMediaStreamTrack for get all reports or set special mediaStreamTack to get reports only this mediaStream.
peerConnection.stats(for: nil, statsOutputLevel: .debug, completionHandler: { reports in
// reports all mediaStreams
}
In your class where you creating peerConnection there you can start a timer like below:
statsTimer = [NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(getStats)
userInfo:nil
repeats:YES];
And getStats be like this:
- (void)getStats {
NSArray<RTCMediaStreamTrack *> *tracks = mediaStream.videoTracks;
tracks = [tracks arrayByAddingObjectsFromArray:// Here mediaStream is instance of RTCMediaStream (NSArray<RTCMediaStreamTrack *> *)_publishStream.mediaStream.audioTracks];
for (RTCMediaStreamTrack *track in tracks) {
[peerConnection statsForTrack:track
statsOutputLevel:RTCStatsOutputLevelStandard
completionHandler:^(NSArray<RTCLegacyStatsReport *> * _Nonnull stats) {
for (RTCLegacyStatsReport *stat in stats) {
if ([stat.type isEqualToString:kRTCStatsTypeSSRC]) {
[self processRTCLegacyStatsReport:stat];
[statsBySSRC setObject:#{ kRTCStatsBytesSent: [stat.values objectForKey:kRTCStatsBytesSent],
kRTCStatsLastDate: [NSDate date]
} forKey:[stat.values objectForKey:kRTCStatsTypeSSRC]];
}
}
}];
}
}
- (void)processRTCLegacyStatsReport:(RTCLegacyStatsReport *)statsReport {
NSString *ssrc = [statsReport.values objectForKey:kRTCStatsTypeSSRC];
NSString *mediaType = [statsReport.values objectForKey:kRTCStatsMediaTypeKey];
unsigned long kbps = [self calculateBitrateForStatsReport:statsReport];
L_INFO(#"RTC Publishing %# Stats Type: %#, ID: %# Dict: %#",
mediaType, statsReport.type, statsReport.reportId, statsReport.values);
L_INFO(#"RTC Publishing %# kbps: %lld", mediaType, kbps)
}
- (unsigned long)calculateBitrateForStatsReport:(RTCLegacyStatsReport *)statsReport {
NSString *ssrc = [statsReport.values objectForKey:kRTCStatsTypeSSRC];
unsigned long bytesSent = [[statsReport.values objectForKey:kRTCStatsBytesSent] intValue];
unsigned long lastBytesSent = [[[statsBySSRC objectForKey:ssrc] objectForKey:kRTCStatsBytesSent] intValue];
NSDate *lastStatsDate = [[statsBySSRC objectForKey:ssrc] objectForKey:kRTCStatsLastDate];
NSTimeInterval seconds = [lastStatsDate timeIntervalSinceNow];
unsigned long kbps = (((bytesSent - lastBytesSent) * 8) / fabs(seconds)) / 1000.0;
return kbps;
}

NSTimer Pause not working

I have setup three buttons with start,stop,pause. and given controls to NSTimer to calculates.start stop button works fine gives me the start and stop time but pausebutton does not gives me accurate time .it actually pause time ..but start again it adds the paused timed and disp[ay.
supoose i pause at 5 second of start and wait for 5 sec then press start...it should display 5 ...but displaying 10..
-(void)start:(NSTimer *)timer
{
if(_timer==nil)
{
startDate =[NSDate date];
_timer=[NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(timer:) userInfo:nil repeats:YES];
}
if(_timer!=nil)
{
float pauseTime = -1*[pauseStart timeIntervalSinceNow];
[_timer setFireDate:[previousFireDate initWithTimeInterval:pauseTime sinceDate:previousFireDate]];
}
}
-(void)timer:(NSTimer *)timer
{
NSInteger secondsSinceStart = (NSInteger)[[NSDate date] timeIntervalSinceDate:startDate];
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];
}
label.text=result;
NSLog(#"time interval -> %#",result);
}
-(void)stop
{
if(_timer!=nil)
{
endDate = [NSDate date];
NSLog(#"endate%#",endDate);
NSTimeInterval interval = [endDate timeIntervalSinceDate:startDate];
NSLog(#"total time %f",interval);
[_timer invalidate];
_timer = nil;
startDate=nil;
}
}
-(void)pause:(NSTimer *)timer
{
pauseStart = [NSDate dateWithTimeIntervalSinceNow:0];
previousFireDate = [_timer fireDate];
[_timer setFireDate:[NSDate distantFuture]];
}
I have created this applicaion on mac os. I think you can understand the logic and even copy this with minor changes...as for UILabel.
In .h
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (assign) IBOutlet NSWindow *window;
- (IBAction)start:(id)sender;
- (IBAction)pause:(id)sender;
- (IBAction)stop:(id)sender;
#property (strong) IBOutlet NSTextField *label;
#property (strong)NSDate *startDate;
#property (strong)NSTimer *timer;
#property (assign)BOOL isRunning;
#property (assign)BOOL isPaused;
#property(assign)NSInteger secondsSinceStart;
#property(assign)NSInteger secondsPaused;
#end
In .m
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
self.label.stringValue=#"00:00:00";
self.isRunning=NO;
self.isPaused=NO;
self.secondsPaused=0;
}
-(void)timerDisplay{
if (self.isPaused) {
self.secondsPaused++;
return;
}
self.secondsSinceStart+=1;
NSInteger seconds = self.secondsSinceStart % 60;
NSInteger minutes = (self.secondsSinceStart / 60) % 60;
NSInteger hours = self.secondsSinceStart / (60 * 60);
NSString *result = nil;
if (self.isRunning && !self.isPaused) {
result = [NSString stringWithFormat:#"%02ld:%02ld:%02ld", hours, minutes, seconds];
self.label.stringValue=result;
}
}
- (IBAction)start:(id)sender {
self.isRunning=!self.isRunning;
self.isPaused=NO;
self.secondsSinceStart=0;
self.label.stringValue=#"00:00:00";
self.startDate =[NSDate date];
if (!self.timer) {
self.timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(timerDisplay) userInfo:nil repeats:YES];
}
}
- (IBAction)pause:(id)sender {
self.isPaused=!self.isPaused;
NSLog(#"pause : %d",self.isPaused);
}
- (IBAction)stop:(id)sender {
self.isRunning=NO;
NSLog(#"start : %#",self.startDate);
NSLog(#"end : %#",[NSDate date]);
NSLog(#"paused : %ld",self.secondsPaused);
NSInteger totalTime=self.secondsSinceStart+self.secondsPaused;
NSInteger seconds = totalTime % 60;
NSInteger minutes = (totalTime / 60) % 60;
NSInteger hours = totalTime / (60 * 60);
NSString *result = result = [NSString stringWithFormat:#"%02ld:%02ld:%02ld", hours, minutes, seconds];
NSLog(#"Total : %#",result);
}
#end
It will never ever work for you because NSTimer cant be pause, it will Start and It will only Stop when you will invalidate it. when it will in valid state it means it is running and when the state is not valid it means Timer is stopped. Thanks

Implementing a Countdown Timer in Objective-c?

I am new to iOS programming. I am working on words matching game. In this game I need to implement time counter which shows minutes and seconds. I want when my game is started my timer to start with 3 minutes. Now I want to decrease this timer in reverse direction with seconds. my code just work for seconds..here is my code:
secondsLeft--;
int seconds = (secondsLeft %3600) % 60;
Timerlbl.text = [NSString stringWithFormat:#"%02d",seconds];
if (seconds==0)
{
UIAlertView *pAlert = [[UIAlertView alloc]initWithTitle:#"Sorry!!"
message:#"TimeOver" delegate:self cancelButtonTitle:#"OK"
otherButtonTitles:#"Cancel",nil];
[pAlert show];
[pAlert release];
}
}
In Viewdidload i call it through timer..
countDown=[NSTimer scheduledTimerWithTimeInterval:5.0 target:self
selector:#selector(TimeOver) userInfo:nil repeats:YES];
pleas any one guide me how can i do it in both minutes and seconds.
You can do it like this(ARC Enabled):-
#interface ViewController()
{
UILabel *progress;
NSTimer *timer;
int currMinute;
int currSeconds;
}
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
progress=[[UILabel alloc] initWithFrame:CGRectMake(80, 15, 100, 50)];
progress.textColor=[UIColor redColor];
[progress setText:#"Time : 3:00"];
progress.backgroundColor=[UIColor clearColor];
[self.view addSubview:progress];
currMinute=3;
currSeconds=00;
// Do any additional setup after loading the view, typically from a nib.
}
-(void)start
{
timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:#selector(timerFired) userInfo:nil repeats:YES];
}
-(void)timerFired
{
if((currMinute>0 || currSeconds>=0) && currMinute>=0)
{
if(currSeconds==0)
{
currMinute-=1;
currSeconds=59;
}
else if(currSeconds>0)
{
currSeconds-=1;
}
if(currMinute>-1)
[progress setText:[NSString stringWithFormat:#"%#%d%#%02d",#"Time : ",currMinute,#":",currSeconds]];
}
else
{
[timer invalidate];
}
}
I know this is old question, but I want to share my way to achieve this. We have method (timeIntervalSinceDate:) to calculate the interval and have fixed amount of seconds to count down. In my case 300 s.
UPDATE JULY, 2015 SWIFT
#IBAction func startTimer(sender: UIButton) {
sender.selected = !sender.selected;
//if selected fire timer, otherwise stop
if (sender.selected) {
self.timer = NSTimer.scheduledTimerWithTimeInterval(0.1, target: self, selector: Selector("updateTimer"), userInfo: nil, repeats: true);
self.startDate = NSDate();
} else {
self.stopTimer();
}
}
func stopTimer() {
self.timer.invalidate();
}
func updateTimer() {
// Create date from the elapsed time
var currentDate:NSDate = NSDate();
var timeInterval:NSTimeInterval = currentDate.timeIntervalSinceDate(self.startDate!);
//300 seconds count down
var timeIntervalCountDown = 300 - timeInterval;
var timerDate:NSDate = NSDate(timeIntervalSince1970: timeIntervalCountDown);
// Create a date formatter
var dateFormatter = NSDateFormatter();
dateFormatter.dateFormat = "mm:ss";
dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0);
// Format the elapsed time and set it to the label
var timeString = dateFormatter.stringFromDate(timerDate);
self.timerLabel?.text = timeString;
}
Working github swift sample project
Objective-C
- (void)updateTimer
{
// Create date from the elapsed time
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate
timeIntervalSinceDate:self.startDate];
NSLog(#"time interval %f",timeInterval);
//300 seconds count down
NSTimeInterval timeIntervalCountDown = 300 - timeInterval;
NSDate *timerDate = [NSDate
dateWithTimeIntervalSince1970:timeIntervalCountDown];
// Create a date formatter
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
// Format the elapsed time and set it to the label
NSString *timeString = [dateFormatter stringFromDate:timerDate];
self.stopWatch.text = timeString;
}
- (void)stopTimer
{
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
[self updateTimer];
}
- (void)startTimer
{
if (self.stopWatchTimer) {
[self.stopWatchTimer invalidate];
self.stopWatchTimer = nil;
}
self.startDate = [NSDate date];
// Create the stop watch timer that fires every 100 ms
self.stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1.0/10.0
target:self
selector:#selector(updateTimer)
userInfo:nil
repeats:YES];
}
UPDATE:
it is extremely expensive to create a NSDateFormatter each time you pass through updateTimer. Far better to create the NSDateFormatter outside the loop and reuse it. Credits: #siburb
In .h file
IBOutlet UILabel* lblTimer;
NSTimer* gameTimer;
In .m file
-(void)viewDidLoad
{
[super viewDidLoad];
[self createTimer];
}
- (void)createTimer
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSRunLoop* runLoop = [NSRunLoop currentRunLoop];
gameTimer = [[NSTimer timerWithTimeInterval:1.00 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES] retain];
[[NSRunLoop currentRunLoop] addTimer:gameTimer forMode:NSDefaultRunLoopMode];
timeCount = 20;
[runLoop run];
[pool release];
}
- (void)timerFired:(NSTimer *)timer
{
if(timeCount == 0)
{
[self timerExpired];
}
else
{
timeCount--;
if(timeCount == 0) {
[timer invalidate];
[self timerExpired];
}
}
lblTimer.text = [NSString stringWithFormat:#"%02d:%02d",timeCount/60, timeCount % 60];
self.title = lblTimer.text;
}
Bind the above Label Outlet with Label in View.
It is working correctly with Me
Simple and less code in Objective-C,
in .h file create objects for Timer and totalSeconds
NSTimer *timer;
int totalSeconds;
.m file
//you can call this method where you want
[self startTimer];
-(void)startOtpTimer {
totalSeconds = 120;//your time
timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self
selector:#selector(updateCountDownTime) userInfo:nil repeats:YES];
}
-(void)updateCountDownTime {
[self populateLabelwithTime:totalSeconds];
if( totalSeconds != 0) {
totalSeconds -= 1;
} else {
[timer invalidate];//stop timer
self.timeLabel.text = #"";//after reach 0 you can set empty string
}
}
- (void)populateLabelwithTime:(int)seconds {
self.timeLabel.text = [NSString stringWithFormat:#"%02d", totalSeconds];
}
You can use NSTimer to achieve this.

NSTimer Lap Time iPhone

This is my code for my stopwatch. It all works except for the lap button function. How would i be able to implement a lap time where when the ib action "lap" is pressed it would store the current time in an array and list the lap times on the view?
I have already tried to create a database but this seemed far to complex for something of this nature.
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize start;
#synthesize stop;
#synthesize lap;
#synthesize reset;
#synthesize lapLabel;
#synthesize stopWatchLabel;
NSDate *startDate;
NSDateFormatter *dateFormatter;
NSTimer *stopWatchTimer;
NSTimeInterval secondsAlreadyRun;
int touchCount;
-(void)showActivity:(NSTimer *)tim {
NSDate *currentDate = [NSDate date];
NSTimeInterval timeInterval = [currentDate timeIntervalSinceDate:startDate];
// Add the saved interval
timeInterval += secondsAlreadyRun;
NSDate *timerDate = [NSDate dateWithTimeIntervalSince1970:timeInterval];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"mm:ss.SS"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneForSecondsFromGMT:0.0]];
NSString *timeString=[dateFormatter stringFromDate:timerDate];
stopWatchLabel.text = timeString;
}
- (IBAction)onStartPressed:(UIButton *)sender {
stopWatchTimer = [NSTimer scheduledTimerWithTimeInterval:1/10
target:self
selector:#selector(showActivity:)
userInfo:nil
repeats:YES];
// Save the new start date every time
startDate = [[NSDate alloc] init]; // equivalent to [[NSDate date] retain];
[stopWatchTimer fire];
touchCount +=1;
if (touchCount == 1)
{
start.hidden = YES;
stop.hidden = NO;
reset.hidden = YES;
lap.hidden = NO;
touchCount = 0;
}
}
- (IBAction)onStopPressed:(UIButton *)sender {
// _Increment_ secondsAlreadyRun to allow for multiple pauses and restarts
secondsAlreadyRun += fabs([startDate timeIntervalSinceNow]);
[stopWatchTimer invalidate];
stopWatchTimer = nil;
stop.hidden = YES;
start.hidden = NO;
reset.hidden = NO;
lap.hidden = YES;
}
- (IBAction)reset:(UIButton *)sender; {
secondsAlreadyRun = 0;
stopWatchLabel.text = #"00:00.00";
}
- (IBAction)lap:(UIButton *)sender; {
//Lap Code will go here.
}
- (void)viewDidUnload {
[self setStart:nil];
[self setStop:nil];
[self setLap:nil];
[self setReset:nil];
[self setLap:nil];
[super viewDidUnload];
}
#end
Just use a NSMutableArray stored in the class. Every time the person clicks the lap-button
For instance call
NSMutableArray *lapTimes;
And in your method do:
- (IBAction)lap:(UIButton *)sender {
double timeSinceStart = [startDate timeIntervalSinceNow];
[lapTimes addObject:[NSNumber numberWithDouble:-timeSinceStart]];
}
timeIntervalSinceNow will return the difference in time between the NSDate object and now in seconds. If the NSDate is earlier then now (like in your case), the returned number will be negative, so you will have to invert it.

How Do I write a Timer in Objective-C?

I am trying to make a stop watch with NSTimer.
I gave the following code:
nst_Timer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:#selector(showTime) userInfo:nil repeats:NO];
and it is not working in milliseconds. It takes more than 1 millisecond.
Don't use NSTimer that way. NSTimer is normally used to fire a selector at some time interval. It isn't high precision and isn't suited to what you want to do.
What you want is a High resolution timer class (using NSDate):
Output:
Total time was: 0.002027 milliseconds
Total time was: 0.000002 seconds
Total time was: 0.000000 minutes
Main:
Timer *timer = [[Timer alloc] init];
[timer startTimer];
// Do some work
[timer stopTimer];
NSLog(#"Total time was: %lf milliseconds", [timer timeElapsedInMilliseconds]);
NSLog(#"Total time was: %lf seconds", [timer timeElapsedInSeconds]);
NSLog(#"Total time was: %lf minutes", [timer timeElapsedInMinutes]);
Edit: Added methods for -timeElapsedInMilliseconds and -timeElapsedInMinutes
Timer.h:
#import <Foundation/Foundation.h>
#interface Timer : NSObject {
NSDate *start;
NSDate *end;
}
- (void) startTimer;
- (void) stopTimer;
- (double) timeElapsedInSeconds;
- (double) timeElapsedInMilliseconds;
- (double) timeElapsedInMinutes;
#end
Timer.m
#import "Timer.h"
#implementation Timer
- (id) init {
self = [super init];
if (self != nil) {
start = nil;
end = nil;
}
return self;
}
- (void) startTimer {
start = [NSDate date];
}
- (void) stopTimer {
end = [NSDate date];
}
- (double) timeElapsedInSeconds {
return [end timeIntervalSinceDate:start];
}
- (double) timeElapsedInMilliseconds {
return [self timeElapsedInSeconds] * 1000.0f;
}
- (double) timeElapsedInMinutes {
return [self timeElapsedInSeconds] / 60.0f;
}
#end