From 38ca7448f302d6bfaf85193a9c49435dac7a3f7c Mon Sep 17 00:00:00 2001 From: Domas Nutautas Date: Mon, 30 Nov 2020 15:00:10 +0200 Subject: [PATCH 1/2] Support nested update and input types --- .../ImplicitFlow/ImplicitFlow+OneOf.swift | 19 ++++++++++- .../Helpers/Internal/BaseIntrefaces.swift | 4 +-- StoryFlowTests/ImplicitFlowTests.swift | 33 +++++++++++++++++++ 3 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift b/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift index dd4fd62..2423607 100644 --- a/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift +++ b/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift @@ -3,7 +3,7 @@ import UIKit func oneOf(_ types: Any.Type, contains type: Any.Type) -> Bool { guard let oneOfType = types as? OneOfNType.Type else { return types == type } - return oneOfType.valueTypes.contains { $0 == type } + return oneOfType.unwrappedValueTypes.contains { $0 == type } } // MARK: - Protocol @@ -14,6 +14,23 @@ protocol OneOfNType { static func create(from value: Any) -> Any? } +extension OneOfNType { + static var unwrappedValueTypes: [Any.Type] { + valueTypes.flatMap { ($0 as? OneOfNType.Type)?.unwrappedValueTypes ?? [$0] } + } + static func wrappedCreate(from value: Any) -> Any? { + for valueType in valueTypes { + if valueType == type(of: value) { + return create(from: value) + } else if let oneOfType = valueType as? OneOfNType.Type, + let nestedValue = oneOfType.wrappedCreate(from: value) { + return create(from: nestedValue) + } + } + return nil + } +} + // MARK: - Conformance extension OneOf2: OneOfNType { diff --git a/Sources/StoryFlow/Interfaces/Helpers/Internal/BaseIntrefaces.swift b/Sources/StoryFlow/Interfaces/Helpers/Internal/BaseIntrefaces.swift index d6d1db8..c2b2446 100644 --- a/Sources/StoryFlow/Interfaces/Helpers/Internal/BaseIntrefaces.swift +++ b/Sources/StoryFlow/Interfaces/Helpers/Internal/BaseIntrefaces.swift @@ -18,7 +18,7 @@ extension InputRequiring where Self: UIViewController { public static func _create(input: Any) -> UIViewController { if let typedInput = input as? InputType { return self.init(input: typedInput) - } else if let typedInput = (InputType.self as? OneOfNType.Type)?.create(from: input) as? InputType { + } else if let typedInput = (InputType.self as? OneOfNType.Type)?.wrappedCreate(from: input) as? InputType { return self.init(input: typedInput) } else { fatalError("Trying to create `\(self)` with uncompatible `input` value: \(input).") @@ -58,7 +58,7 @@ extension UpdateHandling where Self: UIViewController { public func _handleAny(update: Any) { if let update = update as? UpdateType { handle(update: update) - } else if let update = (UpdateType.self as? OneOfNType.Type)?.create(from: update) as? UpdateType { + } else if let update = (UpdateType.self as? OneOfNType.Type)?.wrappedCreate(from: update) as? UpdateType { handle(update: update) } else { fatalError("Trying to update `\(self)` with uncompatible `update` value: \(update).") diff --git a/StoryFlowTests/ImplicitFlowTests.swift b/StoryFlowTests/ImplicitFlowTests.swift index 82a10d8..a9b0214 100644 --- a/StoryFlowTests/ImplicitFlowTests.swift +++ b/StoryFlowTests/ImplicitFlowTests.swift @@ -220,6 +220,39 @@ class ImplicitFlowTests: XCTestCase { XCTAssert(to.update === output) } + func testProduce_itUnwindsToNestedOneOfUpdateType() { + + // Arrange + class T1 {} + class T2 {} + class T3 {} + + class From: UIViewController, OutputProducing { typealias OutputType = T2 } + class To: UIViewController, UpdateHandling { + func handle(update: OneOf2>>) { + guard case .t2(.t2(.t1(let update))) = update else { return } + self.update = update + } + var update: T2! + } + + let to = To().visible() + let from = From() + + to.show(from, sender: nil) + XCTAssert(currentVc.didAppear()) + + let output = T2() + + // Act + from.produce(output) + XCTAssert(currentVc.didDismiss()) + + // Assert + XCTAssert(currentVc == to) + XCTAssert(to.update === output) + } + func testProduce_itUnwindsToOneOfUpdateHandlingVcAndPassesOutput() { // Arrange From a9c2cdf021289ec0bc122c4f902fcbdb3730730c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignas=20Jasiu=CC=84nas?= Date: Mon, 30 Nov 2020 17:14:34 +0200 Subject: [PATCH 2/2] Missing return --- Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift b/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift index 2423607..12544b8 100644 --- a/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift +++ b/Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift @@ -16,7 +16,7 @@ protocol OneOfNType { extension OneOfNType { static var unwrappedValueTypes: [Any.Type] { - valueTypes.flatMap { ($0 as? OneOfNType.Type)?.unwrappedValueTypes ?? [$0] } + return valueTypes.flatMap { ($0 as? OneOfNType.Type)?.unwrappedValueTypes ?? [$0] } } static func wrappedCreate(from value: Any) -> Any? { for valueType in valueTypes {