-
Notifications
You must be signed in to change notification settings - Fork 150
/
Copy pathStopWatch.swift
127 lines (103 loc) · 3.89 KB
/
StopWatch.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
//
// StopWatch.swift
// OpenGpxTracker
//
// Created by merlos on 21/09/14.
//
import Foundation
/// Posible status of the stop watch
enum StopWatchStatus {
/// It is counting time
case started
/// It is not counting time
case stopped
}
///
/// This class handles the logic behind a stop watch timer
/// It has two statuses: started or stopped. When started it counts time.
/// when stopped it does not count time.
///
class StopWatch: NSObject {
/// Temporary elapsed time.
var tmpElapsedTime: TimeInterval = 0.0
/// Time the stopwatch started
var startedTime: TimeInterval = 0.0
/// Current status
var status: StopWatchStatus
/// Defines the interval in which the delegate is called
var timeInterval: TimeInterval = 1.00 // seconds
/// Timer that handles the synchronous notifications calls to `updateElapsedTime`
var timer = Timer()
/// Delegate that receives the time updates every `timeInterval`
weak var delegate: StopWatchDelegate?
/// Initializes the stopWatch with elapsed time 0.00 and `stopped` stop watch status.
override init() {
self.tmpElapsedTime = 0.0 // seconds
self.status = StopWatchStatus.stopped
super.init()
}
/// Start counting time
func start() {
print("StopWatch: started")
self.status = .started
self.startedTime = Date.timeIntervalSinceReferenceDate
timer = Timer.scheduledTimer(timeInterval: timeInterval,
target: self, selector: #selector(StopWatch.updateElapsedTime),
userInfo: nil, repeats: true)
}
/// Stops counting time
func stop() {
print("StopWatch: stopped")
self.status = .stopped
// Add difference between start and stop to elapsed time
let currentTime = Date.timeIntervalSinceReferenceDate
let diff = currentTime - startedTime
tmpElapsedTime += diff
timer.invalidate()
}
/// Sets everything to 0.0
func reset() {
print("StopWatch: reset")
timer.invalidate()
self.tmpElapsedTime = 0.0
self.startedTime = Date.timeIntervalSinceReferenceDate
self.status = .stopped
}
/// Current elapsed time.
var elapsedTime: TimeInterval {
if self.status == .stopped {
return self.tmpElapsedTime
}
let diff = Date.timeIntervalSinceReferenceDate - startedTime
return tmpElapsedTime + diff
}
///
/// Returns the elapsed time as a String with the format `MM:SS` or `HhMM:SS`
///
/// Examples:
/// 1. if elapsed time is 3 min 30 sec, returns `03:30`
/// 2. 3h 40 min 30 sec, returns `3h40:20`
///
var elapsedTimeString: String {
var tmpTime: TimeInterval = self.elapsedTime
// Calculate the minutes and hours in elapsed time.
let hours = UInt32(tmpTime / 3600.0)
tmpTime -= (TimeInterval(hours) * 3600)
let minutes = UInt32(tmpTime / 60.0)
tmpTime -= (TimeInterval(minutes) * 60)
// Calculate the seconds in elapsed time.
let seconds = UInt32(tmpTime)
tmpTime -= TimeInterval(seconds)
// Display hours only if >0
let strHours = hours > 0 ? String(hours) + "h" : ""
// Add the leading zero for minutes, seconds and millseconds and store them as string constants
let strMinutes = minutes > 9 ? String(minutes):"0" + String(minutes)
let strSeconds = seconds > 9 ? String(seconds):"0" + String(seconds)
// Concatenate hours, minutes and seconds
return "\(strHours)\(strMinutes):\(strSeconds)"
}
/// Calls the delegate (didUpdateElapsedTimeString) to inform there was an update of the elapsed time.
@objc func updateElapsedTime() {
self.delegate?.stopWatch(self, didUpdateElapsedTimeString: self.elapsedTimeString)
}
}