セクション 102
ViewController のデータソースを作成
いくつかの短い手順で、多くのことを実行しました。PageViewController は UIPageViewController を使用して、SwiftUI ビューからコンテンツを表示します。次に、スワイプ操作を有効にしてページ間を移動できるようにします。
UIKit ビューコントローラを表す SwiftUI ビューは、SwiftUI が管理し、表現可能なビューのコンテキストの一部として提供する Coordinator の型を定義できます。
ステップ 1
PageViewController 内で入れ子にされた Coordinator クラスを宣言します。
SwiftUI は、UIViewControllerRepresentable 型のコーディネータを管理し、上記で作成したメソッドを呼び出すときにコンテキストの一部として提供します。
    PageViewController.swift
- import SwiftUI
- import UIKit
- struct PageViewController<Page: View>: UIViewControllerRepresentable {
var pages: [Page]
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
transitionStyle: .scroll,
navigationOrientation: .horizontal)
return pageViewController
}
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[UIHostingController(rootView: pages[0])], direction: .forward, animated: true)
}
class Coordinator: NSObject {
var parent: PageViewController
init(_ pageViewController: PageViewController) {
parent = pageViewController
}
}
- }
ステップ 2
別のメソッドを PageViewController に追加して、コーディネータ (cordinator) を作成します。
SwiftUI は、makeUIViewController(context:) の前にこの makeCoordinator() メソッドを呼び出すため、ビューコントローラを構成するときにコーディネータオブジェクトにアクセスできます。
ヒント
このコーディネータを使用して、デリゲート、データソース、そしてターゲットアクションを介したユーザーイベントへの応答など、一般的な Cocoa パターンを実装できます。
    PageViewController.swift
var pages: [Page]
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UIPageViewController {
let pageViewController = UIPageViewController(
ステップ 3
ビューの pages 配列を使用して、コーディネータ内のコントローラの配列を初期化します。
コーディネータは、これらのコントローラを格納するのに適した場所ですが、システムがコントローラを初期化するのは 1 回だけであり、ビューコントローラを更新する必要がある前に行うためです。
    PageViewController.swift
func updateUIViewController(_ pageViewController: UIPageViewController, context: Context) {
pageViewController.setViewControllers(
[context.coordinator.controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject {
var parent: PageViewController
var controllers = [UIViewController]()
init(_ pageViewController: PageViewController) {
parent = pageViewController
controllers = parent.pages.map { UIHostingController(rootView: $0) }
}
}
- }
ステップ 4
UIPageViewControllerDataSource への準拠を Coordinator の型に追加し、2 つの必須メソッドを実装します。
これらの 2 つのメソッドは、ビューコントローラ間の関係を確立するため、それらの間を前後にスワイプできます。
    PageViewController.swift
[context.coordinator.controllers[0]], direction: .forward, animated: true)
}
class Coordinator: NSObject, UIPageViewControllerDataSource {
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]
}
}
- }
ステップ 5
UIPageViewController のデータソースとしてコーディネータを追加します。
    PageViewController.swift
transitionStyle: .scroll,
navigationOrientation: .horizontal)
pageViewController.dataSource = context.coordinator
return pageViewController
}
プログラム全体
ステップ 6
PageView に戻り、ライブプレビューをオンにして、スワイプ操作をテストします。