问题描述
我使用 Parchment 在顶部添加菜单项。主视图的层次结构如下:
导航视图 -> 标签视图 --> 羊皮纸分页视图 ---> 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")
}
}
复制:
- 启动并转到子视图
- 点击主页按钮将应用发送到后台
- 再次打开应用
- 点击返回
- 导航到子视图。导航栏/后退按钮不再存在。
我注意到的:
我尝试使用自定义 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()
,因为数据源数据已经设置。因此,要解决此问题,只需删除/注释掉 reloadData()
调用,因为如果相关状态发生变化,将重新构建 PageController。同样的问题是我调试的错误的原因。
func updateUIViewController(_ pagingViewController: PagingViewController,context: UIViewControllerRepresentableContext<PagingController>) {
context.coordinator.parent = self
if pagingViewController.dataSource == nil {
pagingViewController.dataSource = context.coordinator
}
//else {
// pagingViewController.reloadData()
//}
}