我使用Xcode 14为iOS 16.2和WatchOS 9.1创建了一个定制/学习型iOS应用和手表应用。这两个应用都有一个真实用户。这两个应用使用CoreData在本地存储活动。这两个应用使用WCSession transferUserInfo()将新活动的JSON表示传送到对方设备,然后对方将新活动保存到其CoreData DB中。这运行良好,应用程序视图动态更新。
使用Xcode,我添加了手表小部件扩展的目标,并稍微更新了样板代码,如下所示。
接下来,我想在新活动添加到手表应用程序时更新复杂功能(包括从iOS应用程序传输的活动)。用户每3到8小时添加一次活动,所以我认为设置未来输入日期的时间轴没有意义。复杂功能只需要最近活动的时间,这样它就可以显示自该活动以来经过的时间。
具体来说,当最近Activity的activityTime值更新时,如何将该值从手表应用发送到复杂功能?
import WidgetKit
import SwiftUI
import OSLog
struct Provider: TimelineProvider {
let logger = Logger(subsystem: Bundle.main.bundleIdentifier ?? "", category: "Provider")
func placeholder(in context: Context) -> mostRecentActivityEntry {
mostRecentActivityEntry(date: Date(), activityTime: Date())
}
func getSnapshot(in context: Context, completion: @escaping (mostRecentActivityEntry) -> ()) {
let entry = mostRecentActivityEntry(date: Date(), activityTime: Date())
completion(entry)
}
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
var mostRecentActivityTime: Date?
var entries: [mostRecentActivityEntry] = []
// 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 = mostRecentActivityEntry(date: entryDate, activityTime: mostRecentActivityTime)
entries.append(entry)
}
let timeline = Timeline(entries: entries, policy: .atEnd)
completion(timeline)
}
}
struct mostRecentActivityEntry: TimelineEntry {
var date: Date
var activityTime: Date?
}
struct MostRecentEntryView : View {
var entry: Provider.Entry
var body: some View {
HStack {
Text("Log")
.font(.headline)
.foregroundColor(.purple)
if let time = entry.activityTime {
Text(time, style: .relative)
.font(.headline)
.foregroundColor(.accentColor)
}
Spacer()
}
}
}
@main
struct ActivityLogWatchWidgetExtension: Widget {
let kind: String = "ActivityLogWatchWidgetExtension"
var body: some WidgetConfiguration {
StaticConfiguration(
kind: kind,
provider: Provider()) { entry in
MostRecentEntryView(entry: entry)
}
.configurationDisplayName("Time Since Last Activity")
.description("Displays the time since the last activity.")
}
}
struct ActivityLogWatchWidgetExtension_Previews: PreviewProvider {
static var previews: some View {
MostRecentEntryView(entry: mostRecentActivityEntry(date: Date(), activityTime: Date().addingTimeInterval(-1000)))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
MostRecentEntryView(entry: mostRecentActivityEntry(date: Date(), activityTime: nil))
.previewContext(WidgetPreviewContext(family: .accessoryRectangular))
}
}
1条答案
按热度按时间eivnm1vs1#
堆栈溢出响应
在为此工作了几天之后,对我来说,关键的信息是WidgetKit已经取代了ClockKit,手表应用程序及其复杂功能可以使用UserDefaults共享简单的数据。
我需要为手表应用和手表小工具扩展添加一个“应用组”功能(复杂化)。我使用的组名是“group.[MY PHONE APP BUNDLE IDENTIFIER]",不过最好避免超过40个字符的名称,因为它们在显示时会被截断,但在后台不会。这花了我一些时间。
在手表应用中直接创建新Activity或从手机应用传输新Activity时,我会将mostRecentActivityTime保存为UserDefaults,并通过WidgetCenter重新加载复杂功能的时间轴:
在widget扩展中,我从UserDefaults获取mostRecentEmptyTime值,并向时间轴添加一个条目。当复杂功能仅在手表应用发送新值时发生变化时,.重载策略永远不起作用。
唯一剩下的问题是,手机应用使用transferUserInfo()将新活动传输到手表应用时,只有在手表应用打开后才会更新手表的复杂功能。我不认为使用sendMessage()会有所改善,因为苹果文档指出,“从iOS应用调用[sendMessage]不会唤醒相应的WatchKit扩展。”