1

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

NavigationView -> TabView -> Parchment PagingView ---> NavigationLink(ChildView)

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

在此处输入图像描述

这是要复制的代码:

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. 导航到子视图。导航栏/后退按钮不再存在。

我注意到:

  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 上测试。

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

4

1 回答 1

0

好的,我在调试其他与羊皮纸相关的东西时发现了这个问题。

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

    func updateUIViewController(_ pagingViewController: PagingViewController, context: UIViewControllerRepresentableContext<PagingController>) {
        context.coordinator.parent = self
        if pagingViewController.dataSource == nil {
            pagingViewController.dataSource = context.coordinator
        }
        //else {
        //    pagingViewController.reloadData()
        //}
    }
于 2021-03-04T10:29:51.547 回答