class Background_Timer: ObservableObject {
var cpu_temp_from_bg = ""
@Published var cpu_Temp_copy = ""
let myRT: RepeatingTimer
init() {
myRT = RepeatingTimer(timeInterval: 2)
myRT.eventHandler = {
print("Timer Fired")
self.setCPUTemp()
self.updateCPUTemp()
print("CPU temp: \(self.cpu_Temp_copy)°F")
}
myRT.resume()
}
func updateCPUTemp() {
DispatchQueue.main.sync {
self.cpu_Temp_copy = String(format: "%3.2f", (cpu_temp_from_bg as NSString).doubleValue)
}
}
func setCPUTemp() {
let connection = NSXPCConnection(serviceName: "com.grizz.CPU-Temp-XPC")
connection.remoteObjectInterface = NSXPCInterface(with: CPU_Temp_XPC_Protocol.self)
connection.resume()
let service = connection.remoteObjectProxyWithErrorHandler { error in
print("Received error:", error)
} as? CPU_Temp_XPC_Protocol
service?.getCPUTemp() { response in
self.cpu_temp_from_bg = response
}
}
}
Note that the ‘@Published’ property wrapper is a feature of
swiftUI that allows an object to announce to the UI when
changes occur.
The demo UI for this project, in ‘ContentView.swift’ then
uses this to update a text field:
struct ContentView: View {
@ObservedObject var my_BG_T = Background_Timer()
var body: some View {
VStack {
Text("CPU Temp: \(my_BG_T.cpu_Temp_copy)°F").frame(
minWidth: 200,
idealWidth: 600,
maxWidth: .infinity,
minHeight: 200,
idealHeight: 400,
maxHeight: .infinity,
alignment: .center)
}
}
}
Note also that the ‘Background_Timer’ class uses an intermediate variable, ‘cpu_temp_from_bg’. This is to avoid a warning when trying to update the UI outside of the main thread. The function ‘updateCUPTemp()’ then synchronously updates the published variable to the main thread.