应用再次回到前台后导航栏消失

Navigation bar disappears after the app comes to the foreground again

我正在使用 Parchment 在顶部添加菜单项。主视图的层次结构如下:

导航视图 -> 选项卡视图 --> 羊皮纸分页视图 ---> 导航链接(子视图)

进入子视图然后再返回时一切正常。当我转到 ChildView,然后转到 background/Home 屏幕,然后重新打开时,会出现此问题。如果我单击后退然后再次转到子项,则后退按钮和整个导航栏都会消失。

这里是要复制的代码:

import SwiftUI
import Parchment

@main
struct ParchmentBugApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            TabView {
                PagingView(items: [
                    PagingIndexItem(index: 0, title: "View 0"),
                ]) { item in
                    VStack {
                        NavigationLink(destination: ChildView()) {
                            Text("Go to child view")
                        }
                    }
                    .navigationBarHidden(true)
                }
            }
        }
    }
}

struct ChildView: View {
    var body: some View {
        VStack {
            Text("Child View")
        }
        .navigationBarHidden(false)
        .navigationBarTitle("Child View")
    }
}

要复制:

  1. 启动并转到子视图
  2. 点击主页按钮将应用程序发送到后台
  3. 再次打开应用程序
  4. 点击返回
  5. 导航到子视图。导航 bar/back 按钮不再存在。

我注意到的:

  1. 删除 TabView 可以解决问题。
  2. 删除 PagingView 也会解决问题。

我尝试使用自定义 PagingController 并尝试了各种设置但均未成功。如果有人也想修改设置,这里是自定义 PagingView

struct CustomPagingView<Item: PagingItem, Page: View>: View {
    private let items: [Item]
    private let options: PagingOptions
    private let content: (Item) -> Page
    
    /// Initialize a new `PageView`.
    ///
    /// - Parameters:
    ///   - options: The configuration parameters we want to customize.
    ///   - items: The array of `PagingItem`s to display in the menu.
    ///   - content: A callback that returns the `View` for each item.
    public init(options: PagingOptions = PagingOptions(),
                items: [Item],
                content: @escaping (Item) -> Page) {
        self.options = options
        self.items = items
        self.content = content
    }
    
    public var body: some View {
        PagingController(items: items, options: options,
                         content: content)
    }
    
    struct PagingController: UIViewControllerRepresentable {
        let items: [Item]
        let options: PagingOptions
        let content: (Item) -> Page
        
        func makeCoordinator() -> Coordinator {
            Coordinator(self)
        }
        
        func makeUIViewController(context: UIViewControllerRepresentableContext<PagingController>) -> PagingViewController {
            let pagingViewController = PagingViewController(options: options)
            return pagingViewController
        }
        
        func updateUIViewController(_ pagingViewController: PagingViewController, context: UIViewControllerRepresentableContext<PagingController>) {
            context.coordinator.parent = self
            if pagingViewController.dataSource == nil {
                pagingViewController.dataSource = context.coordinator
            } else {
                pagingViewController.reloadData()
            }
        }
    }
    
    class Coordinator: PagingViewControllerDataSource {
        var parent: PagingController
        
        init(_ pagingController: PagingController) {
            self.parent = pagingController
        }
        
        func numberOfViewControllers(in pagingViewController: PagingViewController) -> Int {
            return parent.items.count
        }
        
        func pagingViewController(_: PagingViewController, viewControllerAt index: Int) -> UIViewController {
            let view = parent.content(parent.items[index])
            return UIHostingController(rootView: view)
        }
        
        func pagingViewController(_: PagingViewController, pagingItemAt index: Int) -> PagingItem {
            return parent.items[index]
        }
    }
}

已在 iOS 模拟器 14.4 和 14.5 以及设备 14.5 beta 2 上测试。

非常感谢任何提示或想法。

好的,我在调试与 Parchment 相关的其他内容时发现了这个问题。

问题是每次包含 SwiftUI 状态发生变化(以及返回前台时)都会调用 updateUIViewController(),并且库提供的 PageController 包装器将调用 reloadData() 因为数据源数据已经设置好了。因此,要解决此问题,只需 remove/comment 退出 reloadData() 调用,因为如果相关状态发生变化,将重新构建 PageController。同样的问题是我正在调试的错误的原因。

    func updateUIViewController(_ pagingViewController: PagingViewController, context: UIViewControllerRepresentableContext<PagingController>) {
        context.coordinator.parent = self
        if pagingViewController.dataSource == nil {
            pagingViewController.dataSource = context.coordinator
        }
        //else {
        //    pagingViewController.reloadData()
        //}
    }