gpt4 book ai didi

ios - UIPageViewController 在 SwiftUI 中滑动 1 次后停止工作

转载 作者:行者123 更新时间:2023-12-01 19:31:59 25 4
gpt4 key购买 nike

我正在关注 SwiftUI 的 Apple 教程,并在“与 UIKit 交互”(https://developer.apple.com/tutorials/swiftui/interfacing-with-uikit)下制作了一个 UIPageController。

在教程中,他们使用 State 属性来更新 currentPage PageView 中的变量.我想尝试一下,并决定要嵌入 PageView在不同的 View 中,有一个 currentPage而是在该父 View 中更新属性。所以,很自然,我更改了 @State属性到 @Binding位于 PageView 的属性(property)为了更新currentPage在 parent 。

但是,当我这样做时, UIPageController 停止工作并继续返回 nil来自 pageViewController(_:viewControllerBefore:) -> UIViewController?在第二次滑动时。

这是代码,我将添加注释以使其不那么繁琐:

struct ContentView: View {
@State var currentPage = 0 // This is the new @State variable which should get updated.

var body: some View {
VStack {
PageView([Text("First page"), Text("Second Page"), Text("Third Page")],
currentPage: self.$currentPage) // Passed a binding to the State variable since I want that to be updated when the page changes.
Text("Page number: \(currentPage)") // Removing this fixes the problem, but I need it here.
}
}
}
struct PageView<Page: View>: View {
var viewControllers: [UIHostingController<Page>]
@Binding var currentPage: Int // This used to be an @State property, but I changed it to a binding since the currentPage variable is now being updated elsewhere (In the view above).

init(_ views: [Page], currentPage: Binding<Int>) {
self.viewControllers = views.map { UIHostingController(rootView: $0) } // Simply wrapping all the views inside ViewControllers for UIPageViewController to use.
self._currentPage = currentPage // Assigning the binding.
}

var body: some View {
PageViewController(controllers: self.viewControllers, currentPage: self.$currentPage)
}
}
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int

func makeCoordinator() -> Coordinator { // Makes the coordinator, irrelevant to the problem
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
// I don't think the problem lies here.
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)

pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator

return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
// I don't think the problem lies here.
pageViewController.setViewControllers(
[self.controllers[currentPage]], direction: .forward, animated: true)
}

class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController

init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}

func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
// This is where I think the problem lies. When the line below is evaluated, nil is returned on the second swipe when it shouldn't be. It works on the first swipe but on the second swipe nil is returned and therefore nothing is presented.
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == parent.controllers.count - 1 {
return parent.controllers.first
}
return parent.controllers[index + 1]
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
if completed, let visibleViewController = pageViewController.viewControllers?.first, let index = parent.controllers.firstIndex(of: visibleViewController) {
parent.currentPage = index
}
}
}
}

另外, 删除 Text来自 ContentView解决了这个问题,但我需要它 - 所以删除它不是一种选择。

如果有人可以解释如何解决我的问题,我将非常感激。 如果您太懒惰,则无需提供代码示例,简单的解释也应该可以完成工作。

提前致谢!

最佳答案

PageView在更新 body 期间重新创建当Text被刷新。避免这种情况的解决方案是使 PageView确认Equatable .

最简单的修复演示如下(仅修改部分)。使用 Xcode 11.4/iOS 13.4 测试

注意:使用相同的 PageView,因为没有提供 PageView2

// ...
var body: some View {
VStack {
PageView([Text("First page"), Text("Second Page"), Text("Third Page")],
currentPage: self.$currentPage)
.equatable() // << here !!
Text("Page number: \(currentPage)")
}
}


struct PageView<Page: View>: View, Equatable { // << confirm !!
static func == (lhs: PageView<Page>, rhs: PageView<Page>) -> Bool {
return true // just for demo, make it meaningful on some property
}

// .. other code goes here

关于ios - UIPageViewController 在 SwiftUI 中滑动 1 次后停止工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62262668/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com