I'm stuck on the following issue, I have created 2 text field in an Hstack where the user can insert the local time in the format of HH:mm and it is converted automatically in UTC time in the second textfield and vice-versa. TO do so I used onchange method, when the variable "localTime" changes, it updates the variable "utcTime" and vice-versa, but when I run the code it enters in an infinite loop because they keep updating each other... any solution how to avoid this?
import SwiftUI
struct TimeView: View {
@Binding var localDate : Date?
@Binding var utcDate : Date?
/// continete l'ora in formato HH:mm
@Binding var localTime : String
@Binding var utcTime : String
@Binding var selectedDate: Date
@State var shouldUpdateUTCTime = true
@State var shouldUpdateLocalTime = true
let dateTimeFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "HH:mm"
formatter.timeZone = TimeZone(identifier: "UTC")
return formatter
}()
@FocusState var isFocused: Bool
var body: some View {
HStack {
TimeTextField(time: $localTime, description: "Local Time")
.multilineTextAlignment(.center)
.keyboardType(.numbersAndPunctuation)
.onChange(of: localTime) { oldValue, newValue in
if shouldUpdateUTCTime {
updateUTCTime()
}
}
TimeTextField(time: $utcTime, description: "UTC")
.multilineTextAlignment(.center)
.keyboardType(.numbersAndPunctuation)
.onChange(of: utcTime) { oldValue, newValue in
if shouldUpdateLocalTime {
updateLocalTime()
}
}
}
}
func updateUTCTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
if let utcDate = dateFormatter.date(from: localTime) {
dateFormatter.timeZone = TimeZone(identifier: "UTC") // convert to utc the local
let utcDateString = dateTimeFormatter.string(from: utcDate)
utcTime = utcDateString
}
}
func updateLocalTime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
if let local = dateFormatter.date(from: utcTime) {
dateFormatter.timeZone = TimeZone.current // convert to current the local
let localDateString = dateTimeFormatter.string(from: local)
localTime = localDateString
}
}
}
enum Field: Hashable {
case universalTime
case localTime
}
@FocusState var focusedState: Field?
Use focusState, add focused modifiers to each of textFields like this:
TextField("", text: $localTime)
.focused($focusedState, equals: .localTime)
TextField("", text: $universalTime)
.focused($focusedState, equals: .universalTime)
and than .onChange modifier check focusState and call the methods based on current / active focusState,
For LocalTime TextField:
.onChange(of: localTime) { _ in
if focusedState == .localTime {
updateUTCTime()
}
}
For UniversalTime TextField:
.onChange(of: universalTime) { _ in
if focusedState == .universalTime {
updateLocalTime()
}
}
Now it will not go into infinite loop.