使用现有页面而不是PageViewController中的初始化控制器



我使用的是本教程中的PageViewController

由于页面被添加为控制器,这里:

controllers = parent.pages.map { UIHostingController(rootView: $0) }

当它们在我的SwiftUI视图中更新时,用户看不到任何更新,因为(我猜)init方法不刷新。

那么我如何能够使用当前的pages而不是实例化controllers数组?

下面是我的代码:

PageViewController.swift

import SwiftUI
import UIKit
struct PageViewController<Page: View>: UIViewControllerRepresentable {
var pages: [Page]
var onLast: () -> AnyView
@Binding var currentPage: Int
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .vertical)
pageViewController.dataSource = context.coordinator
pageViewController.delegate = context.coordinator
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[context.coordinator.controllers[currentPage]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource, UIPageViewControllerDelegate {
var parent: PageViewController
var controllers = [UIViewController]()
init(_ pageViewController: PageViewController) {
parent = pageViewController
controllers = parent.pages.map { UIHostingController(rootView: $0) }
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerBefore viewController: UIViewController) -> UIViewController?
{
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index == 0 {
return controllers.last
}
return controllers[index - 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
viewControllerAfter viewController: UIViewController) -> UIViewController?
{
guard let index = controllers.firstIndex(of: viewController) else {
return nil
}
if index + 1 == controllers.count {
return controllers.first
}
return controllers[index + 1]
}
func pageViewController(
_ pageViewController: UIPageViewController,
didFinishAnimating finished: Bool,
previousViewControllers: [UIViewController],
transitionCompleted completed: Bool) {
if completed,
let visibleViewController = pageViewController.viewControllers?.first,
let index = controllers.firstIndex(of: visibleViewController) {
if index + 1 == controllers.count {
print("index: (index)")
print(controllers.count)
controllers.append(UIHostingController(rootView: parent.onLast()))
}
parent.currentPage = index
}
}
}
}

struct PageView<Page: View>: View, Equatable {
static func == (lhs: PageView<Page>, rhs: PageView<Page>) -> Bool {
return true
}
var pages: [Page]
var onLast: () -> AnyView
@Binding var currentPage: Int
var body: some View {
PageViewController(pages: pages, onLast: onLast, currentPage: $currentPage)
}
}

SwiftUI视图

import SwiftUI
struct Test: View {
@State var color: Color = Color.blue

var body: some View {
PageView(
pages: [
AnyView(
color
),
AnyView(
Color.purple
),
AnyView(Color.green),
AnyView(Color.orange),
],
onLast: {
color = Color.red
},
currentPage: $currentPage
)
.equatable()
}
}

UIKit视图应该在自己的世界里,SwiftUI视图在自己的世界里。实际上,这里期望父状态不会更新桥接UIKit内部深处的东西,即使它看起来像在同一个堆栈中,但实际上它只是一个函数,它被称为god-damn-known-when。

无论如何解决的方法很简单——使用SwiftUI工具来更新SwiftUI视图。在这里,将ObservableObject视图模型与显式视图一起使用并使用该视图模型看起来是合适的,因为它是一个引用类型。

这是一个草图:

class ViewModel: ObservableObject {
@Published var color = Color.blue
}
struct Test: View {
@StateObject var vm = ViewModel()   // << owner !!

var body: some View {
PageView(
pages: [
AnyView(
NativePath(vm: vm) // << inject
),
AnyView(
Color.purple
),
AnyView(Color.green),
AnyView(Color.orange),
],
onLast: {
vm.color = Color.red // << update by ref
},
currentPage: $currentPage
)
.equatable()
}
struct NativePath: View {
@ObservedObject var vm: ViewModel  // << observe explicitly
var body: some View {
vm.color             // << updated
}
}
}

相关内容

  • 没有找到相关文章

最新更新