在"scenePhase"更改时更新"SectionedFetchRequest"



我的应用程序遇到了一个问题。这是一个简单的核心数据应用程序,使用@SectionedFetchRequest获取我的数据并将其格式化为列表。

我编写的sectionIdentifier将对照Calendar检查输入日期,并相应地设置日期格式("今天"、"昨天",然后只设置之前几天的日期(。

问题是,当我早上把应用程序从后台拿出来时,我的数据仍然像昨天一样(即昨天标记为"今天"的东西仍然标记为"今日",尽管它们现在应该是"昨天"。添加新条目并不能强制视图完全重绘和更正部分…只有退出并重新启动应用程序才能做到这一点。这是应用程序的根视图。

我曾尝试将@State对象与scenePhase结合使用,以强制重新绘制列表,但它似乎不起作用(当一天发生变化时,我每天只能测试一次(。

问:当应用程序退出后台时,我如何确保我的条目列表刷新,这样我就不必退出并重新打开它

struct ListView: View {    
@Environment(.managedObjectContext) private var viewContext
@Environment(.scenePhase) var scenePhase
@State private var formID: UUID = UUID()

@SectionedFetchRequest<String, Entry> (
sectionIdentifier: . daySection,
sortDescriptors: [
SortDescriptor(.date, order: .reverse)
]
) var entrySection: SectionedFetchResults<String, Entry>
var body: some View {
NavigationView {
List {
ForEach(entrySection) { section in
Text(“(section.id)”)
ForEach(section) { entry in 
Text(“/(entry.name)”)
}
} 
}
}
.onChange(of: scenePhase) { _ in
formID = UUID()
}
}
}
extension Entry {
@objc var daySection: String {
var formattedDate = ""

if Calendar.current.isDateInToday(date) {
formattedDate = “Today”
} else if  Calendar.current.isDateInYesterday(date) {
formattedDate = “Yesterday”
} else {
formattedDate = date.formatted(.dateTime.weekday(.wide).day().month())
}
return formattedDate
}
}

我认为这里的问题是您的基础数据没有改变,所以核心数据更新没有发生,这意味着您的计算属性不会被调用。

另一方面,您的演示要求正在发生变化:例如,显示为今天的内容现在应显示为昨天,等等

因此,我想知道将条件逻辑转移到表示层是否更好。

在您的核心数据模型中,我会将您的部分标识符更改为区分日期的东西,但除非底层数据更改,否则永远不会更改:

@objc var daySection: Date {
Calendar.current.startOfDay(for: date)
}

因此,区段与当前的区段保持不变,但区段ID值不会更改,直到提取请求中的数据更改为止。

然后,在视图层中,通过将section.id(现在是Date(转换为适当的格式来显示每个节标题:

ForEach(entrySection) { section in
Section {
ForEach(section) { entry in 
// entry details
}
} header: {
Text(formattedHeader(section.id))
}
}
// ...
func formattedHeader(_ date: Date) -> String {
let formattedDate: String

if Calendar.current.isDateInToday(date) {
formattedDate = "Today"
} else if  Calendar.current.isDateInYesterday(date) {
formattedDate = "Yesterday"
} else {
formattedDate = date.formatted(.dateTime.weekday(.wide).day().month())
}
return formattedDate
}

当它醒来时,这可能仍然需要一些提示,但通过这种方式,您可以将获取请求纯粹集中在数据上,并将您的演示选择纯粹放在SwiftUI层中,因此维护后者不需要往返于数据库。

最新更新