В моем приложении SwiftUI у меня в настоящее время есть PageViewController, реализованный с использованием UIKit. Он следует традиционной реализации SwiftUI - UIKit, описанной в Apple SwiftUI UIKit по интеграции учебники .
У меня есть данные, которые заполняют UIViewController, в массиве контроллеров, который передается в PageViewController, предоставленный переменная @Environment
. На другом экране приложения вы можете выполнить действие, которое вызывает обновление объекта Environment, вызывая повторную визуализацию ViewController, который находится в PageViewController.
Эта повторная визуализация, однако, вызывает проблему поскольку ViewController заново создается с новым идентификатором, и поэтому индекс viewController не может быть найден в массиве parent.controller
внутри функции ClassView Coordinator pageViewController. Это приводит к тому, что индекс по умолчанию равен nil, и отключает любое перелистывание в обновленном viewController. Я все еще могу перемещаться между viewControllers, используя точки управления страницей, но я хотел бы определить, как я могу обновить массив parent.controller, чтобы включить новый ViewController и отказаться от старого.
После нескольких часов поиска Я не смог найти способ, как я могу сбросить массив родительского контроллера с новым ViewController, заменив старый вид, который был отброшен. Ниже приведен код для PageViewController.
import SwiftUI
import UIKit
struct PageViewController: UIViewControllerRepresentable {
var controllers: [UIViewController]
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.view.backgroundColor = UIColor.clear
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[controllers[currentPage]], direction: .forward, animated: false)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
self.parent = pageViewController
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController? {
print(parent.controllers)
print(viewController)
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 + 1 == parent.controllers.count {
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
}
}
}
}
После обновления состояния среды, которое заполняет данные для данного ViewController, вызывая повторную визуализацию, класс-координатор может печатать массив контроллеров, которые включают в себя старые ViewController, а также новый ViewController в приведенном ниже аннотированном коде, но я пока не смог найти надежный способ обеспечить эффективную замену старого ViewController старым.
struct PageViewController: UIViewControllerRepresentable {
...
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
...
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController? {
print(parent.controllers)
// prints out array of ViewControllers including old ViewController that has now been
// discarded
// [<_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fd595c93de0>,
// <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fd595c94be0>,
// <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fd595c96830>,
// <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fd595c976b0>]
print(viewController)
// prints out new ViewController that does not exist within the parent.controllers array
// and hence nil is returned from the guard
// <_TtGC7SwiftUI19UIHostingControllerVS_7AnyView_: 0x7fd593721710>
guard let index = parent.controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return parent.controllers.last
}
return parent.controllers[index - 1]
}
...
}
Любая помощь или руководство с этим вопрос будет принята с благодарностью!