Skip to content

Commit

Permalink
Added Destination struct to Extras
Browse files Browse the repository at this point in the history
  • Loading branch information
ekazaev committed Jul 22, 2019
1 parent dfe7a36 commit 35ef6ac
Show file tree
Hide file tree
Showing 282 changed files with 4,178 additions and 1,417 deletions.
2 changes: 2 additions & 0 deletions .jazzy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,8 @@ custom_categories:

- name: Extras
children:
- Destination
- AnyDestination
- InlineInterceptor
- InlineContextTask
- InlinePostTask
Expand Down
4 changes: 2 additions & 2 deletions Example/Podfile.lock
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
PODS:
- RouteComposer (2.0.0)
- RouteComposer (2.0.1)

DEPENDENCIES:
- RouteComposer (from `../`)
Expand All @@ -9,7 +9,7 @@ EXTERNAL SOURCES:
:path: "../"

SPEC CHECKSUMS:
RouteComposer: 9873a32541e93e88b0f4ade02def8f974fbd7d98
RouteComposer: 4d43629ff84986b20d0f4ee8bfe9715762d10e84

PODFILE CHECKSUM: 6dc3a094906d5a0f701bcb325869e4a05ad2ae57

Expand Down
4 changes: 2 additions & 2 deletions Example/Pods/Local Podspecs/RouteComposer.podspec.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Example/Pods/Manifest.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1,950 changes: 605 additions & 1,345 deletions Example/Pods/Pods.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions Example/RouteComposer.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@
8479E2F6200E7A4400320380 /* PromptScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8479E2F3200E7A4400320380 /* PromptScreen.storyboard */; };
8479E30D200E7A7F00320380 /* ExampleConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2F8200E7A7F00320380 /* ExampleConfiguration.swift */; };
8479E30E200E7A7F00320380 /* ExampleScreenTypes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2F9200E7A7F00320380 /* ExampleScreenTypes.swift */; };
8479E30F200E7A7F00320380 /* ExampleDestination.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2FA200E7A7F00320380 /* ExampleDestination.swift */; };
8479E310200E7A7F00320380 /* UIColor.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2FC200E7A7F00320380 /* UIColor.swift */; };
8479E311200E7A7F00320380 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2FD200E7A7F00320380 /* ViewController.swift */; };
8479E312200E7A7F00320380 /* CircleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8479E2FF200E7A7F00320380 /* CircleViewController.swift */; };
Expand Down Expand Up @@ -186,7 +185,6 @@
8479E2F4200E7A4400320380 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/PromptScreen.storyboard; sourceTree = "<group>"; };
8479E2F8200E7A7F00320380 /* ExampleConfiguration.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleConfiguration.swift; sourceTree = "<group>"; };
8479E2F9200E7A7F00320380 /* ExampleScreenTypes.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleScreenTypes.swift; sourceTree = "<group>"; };
8479E2FA200E7A7F00320380 /* ExampleDestination.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleDestination.swift; sourceTree = "<group>"; };
8479E2FC200E7A7F00320380 /* UIColor.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIColor.swift; sourceTree = "<group>"; };
8479E2FD200E7A7F00320380 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
8479E2FF200E7A7F00320380 /* CircleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CircleViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -404,7 +402,6 @@
children = (
8479E2F8200E7A7F00320380 /* ExampleConfiguration.swift */,
8479E2F9200E7A7F00320380 /* ExampleScreenTypes.swift */,
8479E2FA200E7A7F00320380 /* ExampleDestination.swift */,
9AFBCEB028743A7AC55E1CA6 /* ExampleAnalyticsSupport.swift */,
9AFBC560E37AAA325DCE89ED /* ExampleGenericContextTask.swift */,
9AFBC94F95A324DC60F78C23 /* BlurredBackgroundTransitionController.swift */,
Expand Down Expand Up @@ -861,7 +858,6 @@
8479E312200E7A7F00320380 /* CircleViewController.swift in Sources */,
8479E315200E7A7F00320380 /* ColorViewController.swift in Sources */,
8479E318200E7A7F00320380 /* PromptViewController.swift in Sources */,
8479E30F200E7A7F00320380 /* ExampleDestination.swift in Sources */,
9AFBC82E50CBF47FB0A0F2D1 /* CityURLTranslator.swift in Sources */,
9AFBCF519040E699D130072D /* CityDetailViewController.swift in Sources */,
9AFBCAFFB71568FAE9054699 /* CitiesTableViewController.swift in Sources */,
Expand Down
26 changes: 0 additions & 26 deletions Example/RouteComposer/Configuration/ExampleDestination.swift

This file was deleted.

3 changes: 2 additions & 1 deletion Example/RouteComposer/Extensions/Router+Destination.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@ import Foundation
import UIKit
import RouteComposer

/// Simple extension to support `Destination` instance directly by the `Router`.
extension Router {

func navigate<VC: UIViewController, C>(to destination: ExampleDestination<VC, C>, animated: Bool = true, completion: ((_: RoutingResult) -> Void)? = nil) throws {
func navigate<VC: UIViewController, C>(to destination: Destination<VC, C>, animated: Bool = true, completion: ((_: RoutingResult) -> Void)? = nil) throws {
try self.navigate(to: destination.step, with: destination.context, animated: animated, completion: completion)
}

Expand Down
5 changes: 3 additions & 2 deletions Example/RouteComposer/URLTranslators/ColorURLTranslator.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@

import Foundation
import UIKit
import RouteComposer

class ColorURLTranslator: ExampleURLTranslator {

func destination(from url: URL) -> ExampleDestination<UIViewController, Any?>? {
func destination(from url: URL) -> AnyDestination? {
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = urlComponents.queryItems,
let colorItem = queryItems.first(where: { $0.name == "color" }),
let colorValue = colorItem.value else {
return nil
}

return ExampleDestination(step: ConfigurationHolder.configuration.colorScreen, context: colorValue).unwrapped()
return Destination(to: ConfigurationHolder.configuration.colorScreen, with: colorValue).unwrapped()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@

import Foundation
import UIKit
import RouteComposer

protocol ExampleURLTranslator {

func destination(from url: URL) -> ExampleDestination<UIViewController, Any?>?
func destination(from url: URL) -> AnyDestination?

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@

import Foundation
import UIKit
import RouteComposer

// Simplest universal link manager. You can use any library or your own implementation using the similar strategy
// transforming data that is contained in the `URL` into `AnyDestination` instance.
struct ExampleUniversalLinksManager {

private static var translators: [ExampleURLTranslator] = []
Expand All @@ -14,7 +17,7 @@ struct ExampleUniversalLinksManager {
translators.append(translator)
}

static func destination(for url: URL) -> ExampleDestination<UIViewController, Any?>? {
static func destination(for url: URL) -> AnyDestination? {
guard let translator = translators.first(where: { $0.destination(from: url) != nil }) else {
return nil
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,12 @@ class CitiesConfiguration {
// be able to select right cell while we are navigating to the `cityDetails`.
.assemble()

static func citiesList(cityId: Int? = nil) -> ExampleDestination<CitiesTableViewController, Int?> {
return ExampleDestination(step: citiesList, context: cityId)
static func citiesList(cityId: Int? = nil) -> Destination<CitiesTableViewController, Int?> {
return Destination(to: citiesList, with: cityId)
}

static func cityDetail(cityId: Int) -> ExampleDestination<CityDetailViewController, Int> {
return ExampleDestination(step: cityDetails, context: cityId)
static func cityDetail(cityId: Int) -> Destination<CityDetailViewController, Int> {
return Destination(to: cityDetails, with: cityId)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@

import Foundation
import UIKit
import RouteComposer

class CityURLTranslator: ExampleURLTranslator {

func destination(from url: URL) -> ExampleDestination<UIViewController, Any?>? {
func destination(from url: URL) -> AnyDestination? {
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = urlComponents.queryItems,
let cityItem = queryItems.first(where: { $0.name == "city" }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ import RouteComposer

struct LoginConfiguration {

static func login() -> ExampleDestination<LoginViewController, Any?> {
let loginScreen = StepAssembly(finder: ClassFinder<LoginViewController, Any?>(),
static func login() -> Destination<LoginViewController, Void> {
let loginScreen = StepAssembly(finder: ClassFinder<LoginViewController, Void>(),
factory: NilFactory()) //Login view controller will be created when UINavigationController will be loaded from storyboard.
.from(SingleStep(
finder: NilFinder(),
factory: StoryboardFactory<UINavigationController, Any?>(storyboardName: "Login")))
factory: StoryboardFactory<UINavigationController, Void>(storyboardName: "Login")))
.using(GeneralAction.presentModally(presentationStyle: .formSheet))
.from(GeneralStep.current())
.assemble()

return ExampleDestination(step: loginScreen, context: nil)
return Destination(to: loginScreen)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,25 @@ struct ImagesConfigurationWithLibrary {
.from(GeneralStep.current())
.assemble()

static func images() -> ExampleDestination<ImagesViewController, Any?> {
static func images() -> Destination<ImagesViewController, Any?> {
let imagesStep = StepAssembly(
finder: ClassFinder(),
factory: ImagesFactory(delegate: ImagesWithLibraryHandler.shared))
.using(CustomContainerFactory<Any?>.ReplaceRoot())
.from(imagesContainerStep)
.assemble()
return ExampleDestination(step: imagesStep, context: nil)
return Destination(to: imagesStep)
}

static func imageDetails(for imageID: String) -> ExampleDestination<ImageDetailsViewController, String> {
static func imageDetails(for imageID: String) -> Destination<ImageDetailsViewController, String> {
let imageDetailsStep = StepAssembly(
finder: ClassFinder(),
factory: ImageDetailsFactory(delegate: ImagesWithLibraryHandler.shared))
.using(CustomContainerFactory<String>.ReplaceRoot())
.from(imagesContainerStep.adaptingContext())
.assemble()

return ExampleDestination(step: imageDetailsStep, context: imageID)
return Destination(to: imageDetailsStep, with: imageID)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,19 @@

import Foundation
import UIKit
import RouteComposer

class ProductURLTranslator: ExampleURLTranslator {

func destination(from url: URL) -> ExampleDestination<UIViewController, Any?>? {
func destination(from url: URL) -> AnyDestination? {
guard let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false),
let queryItems = urlComponents.queryItems,
let item = queryItems.first(where: { $0.name == "product" }),
let productIdValue = item.value else {
return nil
}

return ExampleDestination(step: ProductConfiguration.productScreen, context: ProductContext(productId: productIdValue, productURL: url)).unwrapped()
return Destination(to: ProductConfiguration.productScreen, with: ProductContext(productId: productIdValue, productURL: url)).unwrapped()
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,12 @@ struct WishListConfiguration {
.from(GeneralStep.current())
.assemble()

static func favorites() -> ExampleDestination<WishListViewController, WishListContext> {
return ExampleDestination(step: wishListScreen, context: WishListContext.favorites)
static func favorites() -> Destination<WishListViewController, WishListContext> {
return Destination(to: wishListScreen, with: WishListContext.favorites)
}

static func collections() -> ExampleDestination<WishListViewController, WishListContext> {
return ExampleDestination(step: wishListScreen, context: WishListContext.collections)
static func collections() -> Destination<WishListViewController, WishListContext> {
return Destination(to: wishListScreen, with: WishListContext.collections)
}

}
3 changes: 2 additions & 1 deletion Example/Tests/RouterTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,8 @@ class RouterTests: XCTestCase {
.assemble()

var routingResult: RoutingResult!
try? router.navigate(to: screenConfig, with: nil, animated: false, completion: { result in
let destination = Destination(to: screenConfig).unwrapped()
try? router.navigate(to: destination.step, with: destination.context, animated: false, completion: { result in
routingResult = result
XCTAssertNotNil(currentViewController.presentedViewController)
XCTAssert(currentViewController.presentedViewController is UINavigationController)
Expand Down
2 changes: 1 addition & 1 deletion RouteComposer.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'RouteComposer'
s.version = '2.0.0'
s.version = '2.0.1'
s.summary = 'Protocol oriented library that helps to handle view controllers composition, navigation and deep linking tasks.'
s.swift_version = '5.0'

Expand Down
65 changes: 65 additions & 0 deletions RouteComposer/Classes/Extra/Destination.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//
// Created by Eugene Kazaev on 2019-07-22.
//

import Foundation
import UIKit

/// `AnyDestination` represents a generic `Destination` that contains the screen configuration for any type
/// of `UIViewController` and the context of any type.
public typealias AnyDestination = Destination<UIViewController, Any?>

/// `Destination` instance represents both final screen configuration and the data to provide. It is useful when
/// there is a need to wrap both values into a single DTO value.
public struct Destination<VC: UIViewController, C> {

/// Final configuration.
public let step: DestinationStep<VC, C>

/// Data to be provided to the configuration.
public let context: C

/// Constructor
///
/// - Parameters:
/// - step: `DestinationStep` instance containing the navigation configuration.
/// - context: `Context` instance to be provided to the configuration.
public init(to step: DestinationStep<VC, C>, with context: C) {
self.step = step
self.context = context
}

/// Transforms into generic representation without information about types.
public func unwrapped() -> AnyDestination {
return AnyDestination(to: step.unsafelyRewrapped(), with: context)
}

}

// MARK: Helper Methods

public extension Destination where C == Any? {

/// Constructor
///
/// - Parameters:
/// - step: `DestinationStep` instance containing the navigation configuration.
init(to step: DestinationStep<VC, C>) {
self.step = step
self.context = nil
}

}

public extension Destination where C == Void {

/// Constructor
///
/// - Parameters:
/// - step: `DestinationStep` instance containing the navigation configuration.
init(to step: DestinationStep<VC, C>) {
self.step = step
self.context = ()
}

}
Loading

0 comments on commit 35ef6ac

Please sign in to comment.