Swift -在小部件中显示值表单API并重新加载小部件



简介;我正在为我的特斯拉汽车做一个项目。特斯拉已经有一个只能添加到"今日视图"选项卡的小部件,当我滑动到"今日视图"时,这个小部件会自动刷新。它看起来是这样的:Image here

我想在我的小部件中完成同样的事情。我基本上有了工作代码,如下所示:

注:我的这个项目仅供实验和个人使用。

extension Date {
func timeAgoDisplay() -> String {
let formatter = RelativeDateTimeFormatter()
formatter.unitsStyle = .full
return formatter.localizedString(for: self, relativeTo: Date())
}
}
import WidgetKit
import SwiftUI
import Intents
import TeslaSwift
struct Provider: IntentTimelineProvider {
func placeholder(in context: Context) -> SimpleEntry {
SimpleEntry(date: Date(), configuration: ConfigurationIntent())
}
func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (SimpleEntry) -> ()) {
let entry = SimpleEntry(date: Date(), configuration: configuration)
completion(entry)
}
func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var entries: [SimpleEntry] = []
// Generate a timeline consisting of five entries an hour apart, starting from the current date.
let currentDate = Date()
for hourOffset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .hour, value: hourOffset, to: currentDate)!
let entry = SimpleEntry(date: entryDate, configuration: configuration)
entries.append(entry)
}
getVehicle() // Run this function to get vehicle info
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct SimpleEntry: TimelineEntry {
let date: Date
let configuration: ConfigurationIntent
}
var lastUpdated = String()
var batteryLevel = Int()
var interiorTemperature = Double()
func getVehicle() {

let apii = TeslaSwift()

if let jsonString = UserDefaults(suiteName: "group.widget")!.string(forKey: "GlobalToken"),
let token: AuthToken = jsonString.decodeJSON(),
let _ = UserDefaults(suiteName: "group.widget")!.string(forKey: "GlobalToken") {
apii.reuse(token: token, email: nil)
}

apii.useMockServer = false
apii.debuggingEnabled = true

let id = UserDefaults(suiteName: "group.widget")!.string(forKey: "GlobalSelectedID")

apii.getVehicle(id!).done {
(vehicle: Vehicle) -> Void in

apii.getAllData(vehicle).done { (extendedVehicle: VehicleExtended) in

batteryLevel = (extendedVehicle.chargeState?.batteryLevel)!
interiorTemperature = (extendedVehicle.climateState?.insideTemperature!.celsius)!

let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy - HH:mm:ss"
let now = Date()
let dateString = formatter.string(from:now)
lastUpdated = dateString

}.catch { (error) in

print("error1: (error)")
}

}.catch { error in
print("error2: (error)")
}
}
struct PWidgetEntryView : View {

var entry: Provider.Entry

var body: some View {
VStack {
Text("Battery: (batteryLevel)%")
Text("Temparature: (String(format: "%.0f", interiorTemperature))")
Text("Last Updated: (lastUpdated)")
.environment(.sizeCategory, .extraSmall)
}
}
}
@main
struct PWidget: Widget {
let kind: String = "PWidget"
var body: some WidgetConfiguration {
IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
PWidgetEntryView(entry: entry)
}
.supportedFamilies([.systemMedium])
.configurationDisplayName("My Widget")
.description("This is an example widget.")
}
}
struct PWidget_Previews: PreviewProvider {
static var previews: some View {
PWidgetEntryView(entry: SimpleEntry(date: Date(), configuration: ConfigurationIntent()))
.previewContext(WidgetPreviewContext(family: .systemMedium))
}
}

那么现在,当使用这个代码时。它可以完美地获取数据,但是小部件没有显示数据。

如果我在lastUpdated = dateString之后添加WidgetCenter.shared.reloadAllTimelines(),小部件更新,但也保持每隔5秒更新一次。这将消耗大量的电池。

我还尝试在func getVehicle() {之外添加var didUpdateManually = false,然后像这样检查是否错误。这使得它更新小部件一次,但永远不会再更新:

if (didUpdateManually == false) {
WidgetCenter.shared.reloadAllTimelines()
didUpdateManually = true
}

所以基本上有两/三件事我试图完成:

1. Display the value from API to my widget (batteryLevel, interiorTemperature and lastUpdated timestamp).
2. If either or both is possible:
2.A: When the widget is added to the Today View tab, I want to automatically update the widget by re-running the `func getVehicle()` and update the info when the user swipe to the Today View tab.
2.B: If the widget is on the home screen page, I want to widget to automatically update when the in the same way as 2A, or update once every hour or so.

对于每隔1小时更新小部件,使用带有两个条目的atEnd Policy:-

func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
getVehicle() // Run this function to get vehicle info
let entries = [
SimpleEntry(date: Date(), configuration: configuration)
SimpleEntry(date: Calendar.current.date(byAdding: .minute, value: 60, to: Date())!, configuration: configuration)
]
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
// If its not updating the widget just call api in getTimeline and on the success of api add timeline entries.

//在我这边,我已经取回日历事件,它是为我工作,希望它也为你工作。由于

相关内容

  • 没有找到相关文章

最新更新