Getting the time remaining in the time interval of a Timer in Swift
Do
let timeRemaining = shootingEngine.fireDate.timeIntervalSince(Date())
Let me know if you have any other questions. Good luck!
Swift 4 Get current timeInterval of Scheduled Timer
You can use "contentTimer.fireDate.timeIntervalSince(Date())" to get the current timeinterval.
How do I find the time interval remaining from NSTimer
You have access to a NSTimer's fireDate
, which tells you when the timer is going to fire again.
The difference between now and the fireDate
is an interval you can calculate using NSDate's timeIntervalSinceDate
API.
E.G. something like:
let fireDate = yourTimer.fireDate
let nowDate = NSDate()
let remainingTimeInterval = nowDate.timeIntervalSinceDate(fireDate)
How to get time remaining on an NSTimer as a double
timer.fireDate.timeIntervalSinceNow
should return the number of seconds remaining until the timer fires as an NSTimeInterval
which is a Double
Swift how to check if timer is done using time from certain variable?
There's an easier way to do this, using a single timer which you use to update a display, and just keep track of whether you are running or walking - something like this
@IBAction func cmdStartStopAction(_ sender: Any)
{
durationTimerDisplay = 0.1 // this will update the display every 0.1 seconds
currentlyRunning = true // assume we start by running
if timerDisplay == nil // this means we are starting the timer
{
durationRun = Double(txtTimerRun.text!)! // assumes you have a text box to enter the times
durationWalk = Double(txtTimerWalk.text!)!
durationRemaining = durationRun // we can use this to display a countdown timer
// start the display update timer
timerDisplay = Timer.scheduledTimer(timeInterval: durationTimerDisplay, target: self, selector: #selector(onTimerDisplay), userInfo: nil, repeats: true)
}
else
{
timerDisplay.invalidate()
timerDisplay = nil
}
}
@objc func onTimerDisplay()
{
durationRemaining -= durationTimerDisplay // count down timer
if durationRemaining <= 0 // switch between running and walking when you reach zero
{
// switch from running to walking, or walking to running
currentlyRunning = !currentlyRunning
if currentlyRunning {
durationRemaining = durationRun
}
else {
durationRemaining = durationWalk
}
}
// create a display using a label lblTimer
if currentlyRunning {
lblTimer.text = String(format: "RUN: %.1f", durationRemaining)
}
else {
lblTimer.text = String(format: "WALK: %.1f", durationRemaining)
}
}
Finding the time between now and at specific time using swift 3
For adding an hour to the current time. Use the below extension
extension Date {
func addHours(_ hours: Int) -> Date {
let seconds: TimeInterval = Double(hours) * 60 * 60
let newDate: Date = self.addingTimeInterval(seconds)
return newDate
}
}
call this function as Date().addHours(1)
To get specific time of current date
func getDateFromHour(hour: Int) -> Date {
let date = Date()
let calendar = Calendar.current
et componentsCurrent = calendar.dateComponents([.year, .month, .day], from: date)
var components = DateComponents()
components.hour = hour
components.minute = 0
components.second = 0
components.month = componentsCurrent.month
components.day = componentsCurrent.day
components.year = componentsCurrent.year
return calendar.date(from: components)!
}
Note: you should use 24-hour clock while passing the parameter hour.
Timer to countdown for 6 hours and stop when time is reached and then start again for another 6 hours when button is pressed
This is what I ended up having to do for it to work for me as intended.
Thanks to the answer from @Burak Köse for steering me in the right direction.
import UIKit
import Foundation
var timer = Timer()
var currentTime = Date()
var compareTime = Date().addingTimeInterval(-21600)
func setupButtonTitle()
{
if UserDefaults.standard.object(forKey: "count6") == nil
{
button.setTitle("PRESS", for: .normal)
button.backgroundColor = .green
}
else
{
button.setTitle("PRESS" + "\nIN " + "\(startTimer()))" , for: .normal)
}
button.addTarget(self, action: #selector(buttonTap), for: .touchUpInside)
}
func startTimer()
{
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(sixHourCountdown), userInfo: nil, repeats: true)
}
@objc func sixHourCountdown()
{
let timeStarted = UserDefaults.standard.object(forKey: "count6")
let timeStart = timeStarted as! Date
let diffComponents = Calendar.current.dateComponents([.hour, .minute, .second], from: compareTime, to: timeStart)
let hour = diffComponents.hour!
let minute = diffComponents.minute!
let second = diffComponents.second!
let timeRemaining = String(format: "%02d:%02d:%02d", hour, minute, second)
compareTime += 1
if hour == 0 && minute == 0 && second == 0 || timeStart < compareTime
{
button.setTitle("PRESS", for: .normal)
button.backgroundColor = .green
timer.invalidate()
}
else
{
button.setTitle("PRESS IN" + "\n\(timeRemaining)", for: .normal)
}
}
@objc func buttonTap()
{
if button.currentTitle != "PRESS"
{
button.backgroundColor = .red
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(2), execute:
{
button.backgroundColor = .yellow
})
}
if button.currentTitle == "PRESS" && button.backgroundColor == .green
{
UserDefaults.standard.set(currentTime, forKey: "count6")
let otherVC = OTHERVC()
self.navigationController?.pushViewController(otherVC, animated: true)
}
}
override func viewDidLoad() {
super.viewDidLoad()
setupButtonTitle()
Stopping timer at defined amount of time in Swift
Start by decoupling your expectations.
A "clock" is a container for the period of time from which it was started to now. Additionally, it could be "restarted", so it may need to know how long each previous run cycle was, this would then be added into the overall duration of the "clock"
The Timer
is simply a way to run some code on periodical bases. Because a Timer
only guarantees "at least" period, it should avoid been used for simple counter addition, as it can cause drift in your calculations (for a simple clock, it's probably not a big deal, but if you need any kind of precision, it's best to avoid it)
SimpleClock
import Foundation
public class SimpleClock {
internal var startedAt: Date? = nil
internal var totalRunningTime: TimeInterval = 0 // Used for pause/resume
var isRunning: Bool = false {
didSet {
if isRunning {
startedAt = Date()
} else {
totalRunningTime += currentCycleDuration
self.startedAt = nil
}
}
}
// This is the amount of time that this cycle has been running,
// that is, the amount of time since the clock was started to now.
// It does not include other cycles
internal var currentCycleDuration: TimeInterval {
guard let startedAt = startedAt else {
return 0
}
return Date().timeIntervalSince(startedAt)
}
func reset() {
isRunning = false
totalRunningTime = 0
}
// This is the "total" amount of time the clock has been allowed
// to run for, excluding periods when the clock was paused
var duration: TimeInterval {
return totalRunningTime + currentCycleDuration
}
}
Okay, this is pretty basic concept. It's just a container for recording when a "cycle" starts and stops and managing the "overall" duration (start/pause/resume cycles)
That's all fine and good, but what we really want is some way to determine if the period has "timeout" or not.
AlarmClock
import Foundation
class AlarmClock: SimpleClock {
var timeout: TimeInterval = 0
var hasExpired: Bool {
return duration >= timeout
}
var timeRemaining: TimeInterval {
return max(timeout - duration, 0)
}
}
All this does is add a concept of a "timeout" period and provides some additional functionality that allows use to easily determine if the clock has expired and the amount of time remaining
Example
Okay, that's all nice a good, but how does this work (and help us)
Okay, this is a really simple example. It has a label and two buttons. One button starts/pauses the clock and the other resets it.
The label displays both the running time and the remaining time of the alarm clock. If he clock expires, it will automatically be reset.
The class contains a Timer
which periodically "ticks" and allows the code to inspect that current state of the alarm clock.
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var durationLabel: UILabel!
@IBOutlet weak var cycleButton: UIButton!
@IBOutlet weak var resetButton: UIButton!
let alarmClock: AlarmClock = {
let clock = AlarmClock()
clock.timeout = 10.0
return clock
}()
var timer: Timer? = nil
var durationFormatter: DateComponentsFormatter {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.minute, .second]
formatter.unitsStyle = .abbreviated
return formatter
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
@IBAction func cycleClock(_ sender: Any) {
alarmClock.isRunning = !alarmClock.isRunning
if alarmClock.isRunning {
timer = Timer.scheduledTimer(timeInterval: 0.5, target: self, selector: #selector(tick), userInfo: nil, repeats: true)
} else {
timer?.invalidate()
timer = nil
}
updateDurationLabel()
updateCycleButtonState()
}
@IBAction func restartClock(_ sender: Any) {
timer?.invalidate()
timer = nil
alarmClock.reset()
updateDurationLabel()
updateCycleButtonState()
}
func updateCycleButtonState() {
if alarmClock.isRunning {
cycleButton.setTitle("Pause", for: [])
} else {
cycleButton.setTitle("Start", for: [])
}
}
func updateDurationLabel() {
durationLabel.text = "\(durationFormatter.string(from: alarmClock.duration)!)/\(durationFormatter.string(from: alarmClock.timeRemaining)!)"
}
@objc func tick() {
print("click")
updateDurationLabel()
if alarmClock.hasExpired {
restartClock(self)
}
}
}
Now, you could also add some kind of "internal" thread to periodically check the state of the clock and call a delegate which could then bee used to update the UI, but the intention here is the decoupling of the concerns, and this means you're not adding yet another thread to the system unnecessarily (not saying you couldn't do, but it's just one more level of complexity I didn't want to add ;))
Related Topics
How to Make a Variable from a String
How to Set Up Multiple Combine Timer Publishers
Url Constructor Doesn't Work with Some Characters
Xcode 8.0 Cbcentralmanager Issue
Animated Curve Line in Swift 3
Swift Cannot Output When Using Nstimer
How to Use the Optional Variable in a Ternary Conditional Operator
How to Correctly Initialize an Unsafepointer in Swift
Swift Why Isn't My Date Object That's (Equatable) Equal After Converting It to a String and Back
Core Data Update in Swift While Selecting Any Row in List Table View Not Working
How to Make Text Typed in Textfield Undeletable
Uibarbuttonitem Action Not Work Uitableview Cell
Setting Title of Uinavigationbar Not Working
Swift Accessing Response from Function
How to Get String from Ascii Code in Swift
Switch Statement for Imported Ns_Options (Rawoptionsettype) in Swift