NavigationSplitView 未更新

问题描述 投票:0回答:2

有人可以帮助我为什么

NavigationLink
没有按预期工作吗? 如下所示(在代码中),我使用
MarkdownWebView(url: <url>)
和 3 个不同的 URL。

但是当我想在它们之间切换时,视图不会更新。 如果我在中间打开另一个视图,它就会起作用。 在 iPhone 上 (

NavigationStack
) 也可以使用。

问题

GIF of issue

我的代码:

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 推送第三行。

如果我推送单独的视图,这效果很好。但它不适用于相同的视图和不同的参数(如上面的帖子所示)。

MarkdownWebView()

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)")
            }
        }
    }
}
ipad swiftui swiftui-navigationlink swiftui-navigationsplitview
2个回答
5
投票

按照您使用

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")
            }
        }
    }
}


0
投票

除了建议的内容之外,您还可以遵循 SwiftUI 尝试做的事情,即重用屏幕上已有的视图。

您只需要注意 URL 更改,因为这无论如何都是视图的副作用:

// MarkdownWebView

.onAppear {
  loadMarkdownFile(url: url)
}
// v add this
.onChange(of: url) {
  loadMarkdownFile(url: url)
}
© www.soinside.com 2019 - 2024. All rights reserved.