问题描述
我正在开发我的第一个iOS 14小部件。我知道小部件大部分是静态的,不能显示动态内容,例如动画或。但是可以更改窗口小部件中的/视图数的布局吗?
由于我是SwiftUI的新手,所以看不到任何更改视图内容的方法。
上下文:
假设一个Todo应用程序,其中小部件应显示最多5个条目的按钮/链接。但是,如果应用程序当前只有3个条目,则该小部件当然应该只显示3个链接。
该应用程序已经提供了今日小部件。在这里,我通过简单地将固定数量的条目(例如5个)的控件(按钮)添加到小部件视图中来解决了这个问题。如果显示的条目数较少,则当小部件更新其视图时,未使用的控件将被隐藏。
在SwiftUI中使用固定数量的条目(链接)创建窗口小部件视图是没有问题的。但是,如何隐藏/删除未使用的视图?
在SwiftUI中,视图是一个some View
变量,我看不到一种动态更改其内容的方法:
struct MyEntryView: View {
var body: some View {
Hstrack {
// Item 1
// Item 2
...
// Item n
}
}
}
解决方法
小部件视图是静态,但是每当有新条目传递给它们时,它们都会重绘。
无法创建在集合更改时会自动更新的窗口小部件视图。
您可以:
- 提前创建条目
- 或在检测到集合更改时强制刷新时间线
在两种情况下,您都需要创建一个条目:
struct SimpleEntry: TimelineEntry {
let date: Date
let items: [String]
}
并在视图中显示其项目:
struct SimpleWidgetEntryView: View {
var entry: SimpleProvider.Entry
var body: some View {
VStack {
ForEach(entry.items,id: \.self) {
Text($0)
}
}
}
}
唯一的区别是创建条目的方式:
您可以:
- 提前创建条目(
items
的大小可能会有所不同):
func getTimeline(in context: Context,completion: @escaping (Timeline<SimpleEntry>) -> Void) {
var entries = [SimpleEntry]()
let currentDate = Date()
for offset in 0 ..< 5 {
let entryDate = Calendar.current.date(byAdding: .minute,value: offset,to: currentDate)!
entries.append(SimpleEntry(date: entryDate,items: Array(repeating: "Test",count: offset + 1)))
}
let timeline = Timeline(entries: entries,policy: .atEnd)
completion(timeline)
}
- 或使用当前数据创建一个Entry,并且只要数据更改,都可以通过调用以下命令刷新窗口小部件:
WidgetCenter.shared.reloadAllTimelines()
(重新加载时间线的频率可能受到限制)。