有人可以帮助我为什么
NavigationLink
没有按预期工作吗?
如下所示(在代码中),我使用 MarkdownWebView(url: <url>)
和 3 个不同的 URL。
但是当我想在它们之间切换时,视图不会更新。 如果我在中间打开另一个视图,它就会起作用。 在 iPhone 上 (
NavigationStack
) 也可以使用。
Section("Legal") {
NavigationLink {
MarkdownWebView(url: "https://<url>/privacy.md", scrollbar: false)
.navigationTitle("Privacy Policy")
} label: {
Text("")
.font(.custom(CustomFonts.FADuotone, size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Privacy Policy", comment: "/"))
}
NavigationLink {
MarkdownWebView(url: "https://<url>/tos.md", scrollbar: false)
.navigationTitle("Terms of use")
} label: {
Text("")
.font(.custom(CustomFonts.FADuotone, size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Terms of Service", comment: "/"))
}
NavigationLink {
MarkdownWebView(url: "https://<url>/licenses.md", scrollbar: false)
.navigationTitle("Licenses")
} label: {
Text("")
.font(.custom(CustomFonts.FADuotone, size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Licenses", comment: "/"))
}
}
这就是 NavigationSplitView 的样子:
var body: some View {
NavigationSplitView(columnVisibility: $navigationVM.selectedColumnVisibility) {
column1Form
.navigationTitle(String(localized: "Dashboard", comment: "/"))
.navigationBarTitleDisplayMode(.large)
} content: {
secondForm
}detail: {
detailForm
}
.navigationSplitViewStyle(.balanced)
}
@ViewBuilder
var secondForm: some View {
switch navigationVM.selectedCategory {
case .findWineries: findWineries()
case .profile: ProfileView()
case .stats: StatisticsView()
case .favWines: FavWineView()
case .favWineries: FavWineriesView()
case .cellar: CellarView()
case .orders: OrderListView()
-> case .settings: SettingsView()
case .none: Text("")
}
}
@ViewBuilder
var detailForm: some View {
switch navigationVM.selectedDetail {
case .map: MapView()
case .order: Text("orderTest")
case .orderDetail: OrderDetailView(Status: .delivered)
case .none: Text("")
}
}
在 SplitView 的第二列中,我导航到 SettingsView() (在代码中用箭头标记)。
从那里(SettingsView)我想用 NavigationLink 推送第三行。
如果我推送单独的视图,这效果很好。但它不适用于相同的视图和不同的参数(如上面的帖子所示)。
import SwiftUI
import MarkdownUI
struct MarkdownWebView: View {
@State var url: String
@State var scrollbar: Bool
@State var error: Bool = false
@State private var fileContent: String? = nil
var body: some View {
VStack {
if let content = fileContent {
ScrollView(showsIndicators: scrollbar) {
Markdown(content)
}
} else {
if (error) {
VStack(spacing: 20) {
Text("")
.font(.custom(CustomFonts.FADuotone, size: 100, relativeTo: .body))
.foregroundColor(.red)
Text("Document not found")
.font(.title)
}
} else {
VStack(spacing: 20) {
ProgressView()
Text("loading")
}
}
}
}
.onAppear {
loadMarkdownFile(url: url)
}
.padding()
}
private func loadMarkdownFile(url: String) {
DispatchQueue.global().async {
guard let fileUrl = URL(string: url) else {
print("File not found")
self.error = true
return
}
do {
let content = try String(contentsOf: fileUrl)
DispatchQueue.main.async {
self.fileContent = content
}
} catch {
self.error = true
print("Error reading file: \(error)")
}
}
}
}
按照您使用
NavigationLink
的方式,.onAppear
中的 MarkdownWebView
仅在第一次查看时调用一次。因此内容不会在其他选择上刷新,因为视图已经可见并且 .onAppear
不会再次被调用。
我可以建议两个选择:
1。又快又脏
为
MarkdownWebView
的每次调用提供不同的 .id
,强制重绘:
struct SettingsView: View {
var body: some View {
List {
Section("Legal") {
NavigationLink {
MarkdownWebView(url: "https://www.lipsum.com", scrollbar: false)
.navigationTitle("Privacy Policy")
.id(1) // here
} label: {
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Privacy Policy", comment: "/"))
}
NavigationLink {
MarkdownWebView(url: "https://www.apple.com", scrollbar: false)
.navigationTitle("Terms of use")
.id(2) // here
} label: {
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Terms of Service", comment: "/"))
}
NavigationLink {
MarkdownWebView(url: "https://www.google.com", scrollbar: false)
.navigationTitle("Licenses")
.id(3) // here
} label: {
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Licenses", comment: "/"))
}
}
}
}
}
2。新的 SwiftUI 导航逻辑
使用
NavigationLink
的新 init 值并提供 .navigationDestination
。
我在这里使用了 Int 值 (1,2,3),但你也可以(并且应该)使用枚举值。
struct SettingsView2: View {
var body: some View {
List {
Section("Legal") {
NavigationLink(value: 1) { // value 1
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Privacy Policy", comment: "/"))
}
NavigationLink(value: 2) { // value 2
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Terms of Service", comment: "/"))
}
NavigationLink(value: 3) { // value 3
Text("")
.font(.system(size: 20))
.frame(width: 30)
.foregroundColor(.gray)
Text(String(localized: "Licenses", comment: "/"))
}
}
}
.navigationDestination(for: Int.self) { value in // define destinations based on value
switch value {
case 1:
MarkdownWebView(url: "https://www.lipsum.com", scrollbar: false)
.navigationTitle("Privacy Policy")
case 2:
MarkdownWebView(url: "https://www.apple.com", scrollbar: false)
.navigationTitle("Terms of use")
case 3:
MarkdownWebView(url: "https://www.google.com", scrollbar: false)
.navigationTitle("Licenses")
default: Text("nothing")
}
}
}
}
除了建议的内容之外,您还可以遵循 SwiftUI 尝试做的事情,即重用屏幕上已有的视图。
您只需要注意 URL 更改,因为这无论如何都是视图的副作用:
// MarkdownWebView
.onAppear {
loadMarkdownFile(url: url)
}
// v add this
.onChange(of: url) {
loadMarkdownFile(url: url)
}