应用再次回到前台后导航栏消失
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")
}
}
要复制:
- 启动并转到子视图
- 点击主页按钮将应用程序发送到后台
- 再次打开应用程序
- 点击返回
- 导航到子视图。导航 bar/back 按钮不再存在。
我注意到的:
- 删除
TabView
可以解决问题。
- 删除
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()
//}
}
我正在使用 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")
}
}
要复制:
- 启动并转到子视图
- 点击主页按钮将应用程序发送到后台
- 再次打开应用程序
- 点击返回
- 导航到子视图。导航 bar/back 按钮不再存在。
我注意到的:
- 删除
TabView
可以解决问题。 - 删除
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()
//}
}