Format Realtime Stopwatch Timer to the Hundredth Using Swift

Format realtime stopwatch timer to the hundredth using Swift

For rapid UI updates you should use a CADisplayLink. Anything faster than the display refresh rate is a waste of processing power since it physically cannot be displayed. It also provides a timestamp of the previous frame so you can try to predict when the next frame will be.

You're calculating CACurrentMediaTime() - timerStarted + elapsedTime multiple times. I would recommend doing it only once and saving it in a local variable.

Consider using NSDateComponentsFormatter. Try to reuse one instance of the formatter rather than creating a new one each time (which is usually the most expensive part). Overall, the less string manipulation you can do, the better.

You can check CACurrentMediaTime at the beginning and end of your display method to see how long it takes. Ideally it should be much less than 16.6ms. Keep an eye on the CPU usage (and general power consumption) in the Xcode debug navigator.

Stop watch working fine only first time in Swift

Your pause action should be:

@IBAction func pause(sender: AnyObject) {

timer.invalidate()
pause = true

}

UPD:

var time = 0
var timer = NSTimer()
var pause = true // 1

func displayResult() {

if pause != true
{
time++
label.text = String(time)
}
}
@IBAction func reset(sender: AnyObject) {

time = 0

label.text = String(time)
timer.invalidate() // 2
pause = true // 3
}


@IBAction func pause(sender: AnyObject) {
timer.invalidate() // 4
pause = true

}

@IBAction func play(sender: AnyObject) {

// 5
if pause == true {
timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: Selector("displayResult") , userInfo: nil, repeats: true)
pause = false
}
}

NSTimer Milliseconds Accuracy

Consider using CADisplayLink to update your interface — it gives you very accurate numbers of the time passed since the previous frame was drawn, so you can always keep your UILabel up to date, regardless of how high or low your framerate is.

Stopwatch Elapsed time after thread execution

Your assumption is wrong:

This is because your Thread execution is asynchronous. You tell your program to start the thread (which will execute at least for 2 seconds), then the main Thread continue execution with your if statement which is false (the thread is still running in the background).

One way to solve this, is to pass the stopwatch to myfunction:

static void myfunction(Stopwatch s)
{
Console.WriteLine("hi");
Thread.Sleep(2000);
Console.WriteLine("hi after 2 sec");
Console.WriteLine("Time elapsed: {0}", s.Elapsed.Seconds.ToString());
}

and then in Main replace your Thread initialization with:

Thread t = new Thread(() => myfunction(s));

Swift timer in milliseconds

As Martin says in his comment, timers have a resolution of 50-100 ms (0.05 to 0.1 seconds). Trying to run a timer with an interval shorter than that will not give reliable results. Also, timers are not realtime. They depend on the run loop they are attached to, and if the run loop gets busy, the firing of the timer gets delays.

Instead of trying to increment a counter each time your timer fires, record the start time when you initiate the timer, and then do some math to figure out how much time has transpired:

var startTime: NSTimeInterval

//Sart the timer
startTime = NSDate.timeIntervalSinceReferenceDate()
NSTimer.scheduledTimerWithTimeInterval(0.02,
target: self,
selector: Selector("advanceTimer:"),
userInfo: nil,
repeats: true)


//And your timer method...
func advanceTimer(timer: NSTimer)
{
//Total time since timer started, in seconds
self.time = NSDate.timeIntervalSinceReferenceDate() - startTime
//The rest of your code goes here
}

EDIT:

The Swift 3 version of this code looks like this:

(Written as a view controller in a test project)

class ViewController: UIViewController {

weak var timer: Timer?
var startTime: Double = 0
var time: Double = 0

@IBOutlet weak var timeValueLabel: UILabel!

/*
When the view controller first appears, record the time and start a timer
*/
override func viewDidAppear(_ animated: Bool) {
startTime = Date().timeIntervalSinceReferenceDate
timer = Timer.scheduledTimer(timeInterval: 0.05,
target: self,
selector: #selector(advanceTimer(timer:)),
userInfo: nil,
repeats: true)
}

//When the view controller is about to disappear, invalidate the timer
override func viewWillDisappear(_ animated: Bool) {
timer?.invalidate()
}


func advanceTimer(timer: Timer) {

//Total time since timer started, in seconds
time = Date().timeIntervalSinceReferenceDate - startTime

//The rest of your code goes here

//Convert the time to a string with 2 decimal places
let timeString = String(format: "%.2f", time)

//Display the time string to a label in our view controller
timeValueLabel.text = timeString
}
}

Display StopWatch Timer animated like the petrol pump meter using NSTimer

You need to manually scroll tableView instead of scrollToRowAtIndexPath because this animation uses its own timer interval and its very difficult or we can say impossible to change its time interval.

So, I am Implementing an API for such kind of problems and made a demo app for you with smooth scrolling as you want.

You need to use an outer timer that fires every 1 second and an internal timer that will fire every 0.03 sec as my tableRow Height is 30 I calculated internal timer interval as :---

Move 30 pixels for 1 sec , then
Move 1 pixel for 0.33 sec inside internal timer.

The Internal timer will invalidate and fire every 1 second as initialized within outer timer.

And internal timer will perform the movement of cell.

dial4 is a tableView

Have a look at my code.

#define rowHeight 30

-(void)startCounter
{
outertimer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(snapCell) userInfo:nil repeats:YES];
}

-(void)stopCounter
{
[outertimer invalidate];
}

-(void)snapCell
{
NSLog(@"Initialize Internal timer %i",secLsb);
secLsb++;

if (secLsb==10) {
[dial4 setContentOffset:CGPointMake(0, 0) animated:NO];
secLsb=0;
NSLog(@"dial content offset y is %f",dial4.contentOffset.y);
}

[internaltimer invalidate];
internaltimer=[NSTimer scheduledTimerWithTimeInterval:0.03
target:self
selector:@selector(automaticScroll)
userInfo:nil
repeats:YES];
}

-(void)automaticScroll
{
NSLog(@"val is & y ======== %f",dial4.contentOffset.y);

[dial4 setContentOffset:CGPointMake(dial4.contentOffset.x,dial4.contentOffset.y+1) animated:NO];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return rowHeight;
}

Have a look at Time Counter



Related Topics



Leave a reply



Submit