Make SplitScreenContainerViewController generic
MODIFY
swift/Samples/SplitScreenContainer/DemoApp/AppDelegate.swift
swift/Samples/SplitScreenContainer/DemoApp/AppDelegate.swift
import UIKit
import Workflow
import WorkflowUI
+import SplitScreenContainer
@UIApplicationMain
@@ -42,3 +43,11 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
}
}
+
+extension ViewRegistry {
+
+ public mutating func registerSplitScreenContainer() {
+ self.register(screenViewControllerType: SplitScreenContainerViewController<AnyScreen, BaseScreen>.self)
+ }
+
+}

MODIFY
swift/Samples/SplitScreenContainer/DemoApp/DemoWorkflow.swift
swift/Samples/SplitScreenContainer/DemoApp/DemoWorkflow.swift
@@ -66,7 +66,7 @@ extension DemoWorkflow {
extension DemoWorkflow {
- typealias Rendering = SplitScreenContainerScreen
+ typealias Rendering = SplitScreenContainerScreen<AnyScreen, BaseScreen>
private static let sizes: [CGFloat] = [.quarter, .third, .half, 0.75]
@@ -74,7 +74,7 @@ extension DemoWorkflow {
let sink = context.makeSink(of: Action.self)
return SplitScreenContainerScreen(
- leftScreen: BaseScreen(title: "Left screen", backgroundColor: .red, viewTapped: { sink.send(.viewTapped) }),
+ leftScreen: AnyScreen(BaseScreen(title: "Left screen", backgroundColor: .red, viewTapped: { sink.send(.viewTapped) })),
rightScreen: BaseScreen(title: "Right screen", backgroundColor: .green, viewTapped: { sink.send(.viewTapped) }),
ratio: DemoWorkflow.sizes[state % DemoWorkflow.sizes.count]
)

MODIFY
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerScreen.swift
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerScreen.swift
@@ -17,13 +17,13 @@ import WorkflowUI
/// A `SplitScreenContainerScreen` displays two screens side by side with a separator in between.
-public struct SplitScreenContainerScreen: Screen {
+public struct SplitScreenContainerScreen<LeftScreenType: Screen, RightScreenType: Screen>: Screen {
/// The screen displayed to the left of the separator.
- public let leftScreen: AnyScreen
+ public let leftScreen: LeftScreenType
/// The screen displayed to the right of the separator.
- public let rightScreen: AnyScreen
+ public let rightScreen: RightScreenType
/// The ratio of `leftScreen`'s width relative to that of `rightScreen`. Defaults to `.third`.
public let ratio: CGFloat
@@ -31,14 +31,14 @@ public struct SplitScreenContainerScreen: Screen {
/// The color of the `separatorView` displayed between `leftScreen`'s and `rightScreen`'s views.
public let separatorColor: UIColor
- public init<LeftScreenType: Screen, RightScreenType: Screen>(
+ public init(
leftScreen: LeftScreenType,
rightScreen: RightScreenType,
ratio: CGFloat = .third,
separatorColor: UIColor = .black
) {
- self.leftScreen = AnyScreen(leftScreen)
- self.rightScreen = AnyScreen(rightScreen)
+ self.leftScreen = leftScreen
+ self.rightScreen = rightScreen
self.ratio = ratio
self.separatorColor = separatorColor
}

MODIFY
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerViewController.swift
swift/Samples/SplitScreenContainer/Sources/SplitScreenContainerViewController.swift
import Workflow
import WorkflowUI
-extension ViewRegistry {
+public final class SplitScreenContainerViewController<LeftScreenType: Screen, RightScreenType: Screen>: ScreenViewController<SplitScreenContainerScreen<LeftScreenType, RightScreenType>> {
- public mutating func registerSplitScreenContainer() {
- self.register(screenViewControllerType: SplitScreenContainerViewController.self)
- }
-
-}
-
-
-final class SplitScreenContainerViewController: ScreenViewController<SplitScreenContainerScreen> {
-
- private var leftContentViewController: ScreenViewController<AnyScreen>? = nil
+ private var leftContentViewController: ScreenViewController<LeftScreenType>? = nil
private lazy var leftContainerView: UIView = .init()
private var leftContainerViewWidthConstraint: NSLayoutConstraint?
private lazy var separatorView: UIView = .init()
- private var rightContentViewController: ScreenViewController<AnyScreen>? = nil
+ private var rightContentViewController: ScreenViewController<RightScreenType>? = nil
private lazy var rightContainerView: UIView = .init()
- required init(screen: SplitScreenContainerScreen, viewRegistry: ViewRegistry) {
+ required init(screen: SplitScreenContainerScreen<LeftScreenType, RightScreenType>, viewRegistry: ViewRegistry) {
super.init(screen: screen, viewRegistry: viewRegistry)
update(with: screen)
}
- override func screenDidChange(from previousScreen: SplitScreenContainerScreen) {
+ override public func screenDidChange(from previousScreen: SplitScreenContainerScreen<LeftScreenType, RightScreenType>) {
update(with: screen)
}
- private func update(with screen: SplitScreenContainerScreen) {
+ private func update(with screen: SplitScreenContainerScreen<LeftScreenType, RightScreenType>) {
separatorView.backgroundColor = screen.separatorColor
- if let leftContentViewController = leftContentViewController {
- if leftContentViewController.screenType == type(of: screen.leftScreen) {
- leftContentViewController.update(screen: screen.leftScreen)
- } else {
- leftContentViewController.willMove(toParent: nil)
- leftContentViewController.view.removeFromSuperview()
- leftContentViewController.removeFromParent()
-
- self.leftContentViewController = embed(screen.leftScreen, in: leftContainerView)
- }
- } else {
- self.leftContentViewController = embed(screen.leftScreen, in: leftContainerView)
- }
-
- if let rightContentViewController = rightContentViewController {
- if rightContentViewController.screenType == type(of: screen.rightScreen) {
- rightContentViewController.update(screen: screen.rightScreen)
- } else {
- rightContentViewController.willMove(toParent: nil)
- rightContentViewController.view.removeFromSuperview()
- rightContentViewController.removeFromParent()
-
- self.rightContentViewController = embed(screen.rightScreen, in: rightContainerView)
- }
- } else {
- self.rightContentViewController = embed(screen.rightScreen, in: rightContainerView)
- }
+ leftContentViewController?.update(screen: screen.leftScreen)
+ rightContentViewController?.update(screen: screen.rightScreen)
if (leftContainerViewWidthConstraint?.multiplier != screen.ratio) {
updateWidthConstraints(ratio: screen.ratio, animated: true)
}
}
- private func embed(_ screen: AnyScreen, in containerView: UIView) -> ScreenViewController<AnyScreen> {
- let viewController = viewRegistry.provideView(for: screen)
-
- addChild(viewController)
-
- viewController.view.translatesAutoresizingMaskIntoConstraints = false
- containerView.addSubview(viewController.view)
-
- NSLayoutConstraint.activate([
- viewController.view.topAnchor.constraint(equalTo: containerView.topAnchor),
- viewController.view.rightAnchor.constraint(equalTo: containerView.rightAnchor),
- viewController.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
- viewController.view.leftAnchor.constraint(equalTo: containerView.leftAnchor),
- ])
-
- viewController.didMove(toParent: self)
-
- return viewController
- }
-
- override func viewDidLoad() {
+ override public func viewDidLoad() {
super.viewDidLoad()
leftContainerView.translatesAutoresizingMaskIntoConstraints = false
@@ -130,6 +76,29 @@ final class SplitScreenContainerViewController: ScreenViewController<SplitScreen
])
updateWidthConstraints(ratio: screen.ratio, animated: false)
+
+ self.leftContentViewController = embed(screen.leftScreen, in: leftContainerView)
+ self.rightContentViewController = embed(screen.rightScreen, in: rightContainerView)
+ }
+
+ private func embed<ScreenType: Screen>(_ screen: ScreenType, in containerView: UIView) -> ScreenViewController<ScreenType> {
+ let viewController = viewRegistry.provideView(for: screen)
+
+ addChild(viewController)
+
+ viewController.view.translatesAutoresizingMaskIntoConstraints = false
+ containerView.addSubview(viewController.view)
+
+ NSLayoutConstraint.activate([
+ viewController.view.topAnchor.constraint(equalTo: containerView.topAnchor),
+ viewController.view.rightAnchor.constraint(equalTo: containerView.rightAnchor),
+ viewController.view.bottomAnchor.constraint(equalTo: containerView.bottomAnchor),
+ viewController.view.leftAnchor.constraint(equalTo: containerView.leftAnchor),
+ ])
+
+ viewController.didMove(toParent: self)
+
+ return viewController
}
private func updateWidthConstraints(ratio: CGFloat, animated: Bool) {

Make SplitScreenContainerViewController generic