I want my swift code to call the selector at the beginning of every hour. So 1 pm 2pm 4pm etc. Every time it is the beginning of the hour the code should call the function tick. Every hour the background color of the label should alternate colors. I have added a var for a current date and a function to convert the time to the military time.
import UIKit
class ViewController: UIViewController {
var box = UILabel()
var timer = Timer()
var currentDateTime = Date()
lazy var dateFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "hh:mm" // or "hh:mm a" if you need to have am or pm symbols
return formatter
}()
override func viewDidLoad() {
super.viewDidLoad()
//somehow make timer inertval on the hour
timer = Timer.scheduledTimer(timeInterval: 3600.0, target: self, selector:#selector(self.tick) , userInfo: nil, repeats: true)
box.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(box)
box.backgroundColor = .red
NSLayoutConstraint.activate([
box.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5),
box.centerXAnchor.constraint(equalTo: view.centerXAnchor),
box.centerYAnchor.constraint(equalTo: view.centerYAnchor),
])
}
var count = 0
@objc func tick() {
if count % 2 == 0 {
box.backgroundColor = .cyan
count +=1
}
else {
box.backgroundColor = .red
count +=1
}
}
func getMinutesFromDate(date: Date) -> Int {
let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: date)
let minutes = ((dateComponents.hour ?? 0) * 60) + (dateComponents.minute ?? 0)
return minutes
}
}
Humm , Oh sorry! Thought you knew how to use the timer? I don’t
I was going to use your example to try and build am event timer, myself.
I would think if you get a timer running with minutes and seconds displaying you could then use it to experiment at taking an action when every minute or few seconds have passed.?.
Sorry I am not much help with the timer at the moment !
Hi @timswift , I am very far from an expert but here is the way I would have go
import UIKit
class ViewController: UIViewController {
var box = UILabel()
// As stated by @catzshadowy for your sample with 2 background states
// I tend to prefer a boolean state instead of the modulo of a number.
// I am using the property observer of boxState to change the label color
// I have no clue about efficiency but I like very much property observers,
// because it seems cleaner and easiest to read at least in my mind
var boxState: Bool? {
didSet {
box.backgroundColor = boxState! ? .red : .blue
}
}
// keep a reference to timer
var timer: Timer?
override func viewDidLoad()
{
// init boxState to give the first red backgroundColor
boxState = true
// copy/paste of your sample here
box.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(box)
NSLayoutConstraint.activate([
box.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 0.5),
box.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.5),
box.centerXAnchor.constraint(equalTo: view.centerXAnchor),
box.centerYAnchor.constraint(equalTo: view.centerYAnchor)
])
super.viewDidLoad()
// Start timer now
startTimer()
}
func startTimer()
{
// not really useful in this sample, but I tend to clear stuff before setting it
stopTimer()
// get current date components
var components = Calendar.current.dateComponents([ .year, .month, .day, .hour, .minute, .second, .timeZone ], from: Date())
// update components to define next hour:00:00 from now
components.hour = (components.hour ?? 0) + 1
components.minute = 0
components.second = 0
// set repeat interval to 3600 seconds
let interval:TimeInterval = 3600
// for my tests I used a 5 seconds timer, because it was too long to wait for a full hour :p
// let interval:TimeInterval = 5
// components.second = ( components.second ?? 0) + 5
// create the next update date from components
if let date = Calendar.current.date(from: components)
{
// define the timer from next date repeated every set interval
// I am using escaping closure here because I really hate @objc stuff
timer = Timer(fire: date, interval: interval, repeats: true) {
[weak self] _ in
guard let self = self else { return }
// toggle box state
self.boxState = !self.boxState!
}
// start the never ending loop timer
RunLoop.main.add(timer!, forMode: .common)
}
}
func stopTimer()
{
// get confident the timer is not nil
guard let timer = timer else { return }
// stop it
timer.invalidate()
}
}