gre*_*rey 6 swiftui swiftui-navigationlink swiftui-navigationsplitview
我试图NavigationSplitView与其中DetailView包含taskor 的a 一起使用onAppear,但它似乎只运行一次。
enum MenuItem: String, Hashable, Identifiable, CaseIterable {
case menu1
case menu2
case menu3
case menu4
case menu5
var id: String { rawValue }
}
struct ContentView: View {
@State var selection: MenuItem?
var body: some View {
NavigationSplitView {
List(MenuItem.allCases, selection: $selection) { item in
NavigationLink(value: item) {
Text(item.rawValue)
}
}
} detail: {
if let selection {
DetailView(menuItem: selection)
} else {
Text("Default")
}
}
}
}
struct DetailView: View {
let menuItem: MenuItem
@State var name = "Name"
var body: some View {
VStack {
Text(menuItem.id)
Text(name)
}
.task {
// This should be an async setup code
// but for the sake of simplicity
// I just made it like this
name = menuItem.id
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以使用它onChange(of: selection)作为解决方法,然后将我的设置代码放在那里。但是还有其他方法可以在我的内部制作task或onAppear工作DetailView吗?
将视图id基于选择并不是一个好主意。body每次选择更改时,它都会强制进行整个重建,这将导致随着视图层次结构的增长而导致性能下降。
相反,您可以使用task(id:priority:_:)的替代形式在值更改时启动任务selection,如下所示:
struct ContentView: View {\n @State var selection: MenuItem?\n \n var body: some View {\n NavigationSplitView {\n \xe2\x80\xa6\n } detail: {\n \xe2\x80\xa6\n }\n .task(id: selection, priority: .userInitiated) { sel in\n print("selection changed:", sel)\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n
这是 SwiftUI 优化,它仅重新创建依赖部分。
一个可能的解决方案是使整个主体依赖于菜单项,因此它将完全重新创建并再次调用任务,例如
struct DetailView: View {
let menuItem: MenuItem
@State var name = "Name"
var body: some View {
VStack {
Text(menuItem.id)
Text(name)
}
.task {
// This should be an async setup code
// but for the sake of simplicity
// I just made it like this
name = menuItem.id
}
.id(menuItem.id) // << here !!
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
966 次 |
| 最近记录: |