Skip to content

Commit

Permalink
Merge pull request #15 from trafi/feature/unwind-of-n
Browse files Browse the repository at this point in the history
Support nested update and input types
  • Loading branch information
Ignelios authored Nov 30, 2020
2 parents 46daeb2 + a9c2cdf commit cee795c
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 3 deletions.
19 changes: 18 additions & 1 deletion Sources/StoryFlow/Flow/ImplicitFlow/ImplicitFlow+OneOf.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -14,6 +14,23 @@ protocol OneOfNType {
static func create(from value: Any) -> Any?
}

extension OneOfNType {
static var unwrappedValueTypes: [Any.Type] {
return 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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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).")
Expand Down Expand Up @@ -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).")
Expand Down
33 changes: 33 additions & 0 deletions StoryFlowTests/ImplicitFlowTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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<T1, OneOf2<T3, OneOf2<T2, T3>>>) {
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
Expand Down

0 comments on commit cee795c

Please sign in to comment.