use*_*594 6 xcode swift swiftui swiftui-navigationlink swiftui-navigationview
自 Xcode 12.5 以来,我看到很多“无法呈现。请提交错误”。console 登录 Xcode 控制台,我记得在 12.5 之前没有看到过。
当我NavigationLink从父视图导航到子视图,并且子视图中的逻辑更新父视图所依赖的状态之一时,会显示此消息。
下面是一个示例伪代码,其中消息列表显示在父视图中,消息详细信息显示在列表的子视图中,最后是独立设置子视图。
struct MessageListView: View {
...
@StateObject var messageList = MessageList()
var body: some View {
debugPrint("!!MessageListView has been redrawn!!")
return VStack {
NavigationLink(destination:SettingsView()){
Text("Go to settings")
}
ForEach(messageList.data.sorted(by: {$0.key < $1.key}), id:\.key) { k, m in
NavigationLink(destination:MessageView(message:...){
Text(m.text)
}
}
}
}
}
struct MessageView: View {
...
@ObservedObject var messageList : MessageList
@ObservedObject var message : Message
...
var body: some View {
Text(...)
.onAppear {
messageList.readAndIncrement(message.id) //<- This updates both this view & parent view.
}
}
}
class MessageList : ObservableObject {
@Published var data : [String:Message] = [:]
func readAndIncrement(id: String){
//Modify one of the message in dictionary.
}
}
Run Code Online (Sandbox Code Playgroud)
因此,当用户单击消息并遍历导航时,如下所示,
MessageListView -> MessageView
Run Code Online (Sandbox Code Playgroud)
一旦MessageView出现在屏幕上,由于 中的逻辑,它将增加消息的“读取计数” ,同时onAppear更新数据。MessageListView
一旦发生这种情况,MessageListView观察 MessageList 对象的父视图似乎就会更新,会发生以下两件事。
debugPrint将在控制台上打印消息!!MessageListView has been redrawn!!(来自上面的源代码),这证明父视图已更新,而导航当前显示子视图。因此,当我在子视图中查看和交互时更新父视图的观察数据时,SwiftUI 似乎抛出“无法呈现”错误日志,但我不确定如何正确修复以消除此错误。
我认为这不是一个错误,但我的错误是由于以下原因。
当用户进入完全不同的视图时,类似
MessageListView -> SettingsView
Run Code Online (Sandbox Code Playgroud)
并且如果满足以下两个条件,
然后,父视图 (MessageListView) 会针对其依赖模型的每次更新进行重绘,并且子视图开始自行堆叠,如下所示。
至少,在上述情况下,Unable to present. Please file a bug.不会显示在控制台中。
在 iOS 14.5 & Xcode 12.5补丁说明中,唯一相关的评论NavigationLink如下,但这似乎与我的情况无关。
仅本地状态不同的 NavigationLink 目标现在会在按预期在链接之间切换时重置该状态。(72117345)
所以我的问题是...在这种情况下如何正确管理状态(或解耦它们),并且不会导致 SwiftUI 导航中的时髦?
在屏幕上呈现子视图时更新父视图的状态数据是否违反 SwiftUI 的范例,或者这只是NavigationLinkXcode 12.5 中的一个错误?
我正在回答我自己关于我找到的解决方法的问题。对我有用的解决方案是使用Class而不是Struct更新Class. 这阻止了View正在监视@Published数组/列表的 被更新。
以前,我使用的是StructforMessage类型。最终发生的情况是,对结构/消息的属性之一的任何更改都会触发 UI 更新(这是预期的),即使不是View直接监视结构本身,而是监视结构列表(在我的例子中MessageList是类的属性) data.)。
我Message从转换Struct为Class实现ObservableObject并更新其属性。当列表元素之一必须更新时,这可以防止依赖于消息列表的父视图被重绘。
总之,当您将@Published注释分配给 数组时Struct,列表项添加/删除以及对列表中结构项的属性之一的任何更改都将触发 SwiftUI 中的依赖视图更新。
另一方面,如果您将@Published注释分配给 数组Class,则只有列表项添加/删除才会触发 SwiftUI 更新。对类属性之一的任何更改都不会触发 SwiftUI 中的相关视图更新。
| 归档时间: |
|
| 查看次数: |
1867 次 |
| 最近记录: |