Slather logo

Coverage for "Factory.swift" : 100.00%

(22 of 22 relevant lines covered)

RouteComposer/Classes/Factory.swift

1
//
2
// RouteComposer
3
// Factory.swift
4
// https://github.com/ekazaev/route-composer
5
//
6
// Created by Eugene Kazaev in 2018-2022.
7
// Distributed under the MIT license.
8
//
9
// Become a sponsor:
10
// https://github.com/sponsors/ekazaev
11
//
12
13
import UIKit
14
15
/// The `Factory` protocol should be implemented by the instance that produces any types of the view controllers.
16
///
17
/// **NB**
18
///
19
/// `Context` represents a payload that you need to pass to your `UIViewController` and something that distinguishes it from others.
20
/// It is not a View Model or some kind of Presenter. It is the missing piece of information. If your view controller requires a
21
/// `productID` to display its content, and the `productID` is a `UUID`, then the type of `Context` is the `UUID`. The internal logic
22
/// belongs to the view controller. `Context` answers the questions *What to I need to present a ProductViewController* and *Am I
23
/// already presenting a ProductViewController for this product*.
24
public protocol Factory: AbstractFactory {
25
26
    // MARK: Associated types
27
28
    /// Type of `UIViewController` that `Factory` can build
29
    associatedtype ViewController
30
31
    /// `Context` to be passed into `UIViewController`
32
    associatedtype Context
33
34
    // MARK: Methods to implement
35
36
    /// Builds a `UIViewController` that will be integrated into the stack
37
    ///
38
    /// - Parameter context: A `Context` instance that is provided to the `Router`.
39
    /// - Returns: The built `UIViewController` instance.
40
    /// - Throws: The `RoutingError` if build did not succeed.
41
    func build(with context: Context) throws -> ViewController
42
43
}
44
45
// MARK: Default implementation
46
47
public extension Factory {
48
49
    /// Default implementation does nothing
50
    mutating func prepare(with context: Context) throws {}
136x
51
52
}
53
54
// MARK: Helper methods
55
56
public extension Factory {
57
58
    /// Prepares the `Factory` and builds its `UIViewController`
59
    func execute(with context: Context) throws -> ViewController {
4x
60
        var factory = self
4x
61
        try factory.prepare(with: context)
4x
62
        return try factory.build(with: context)
4x
63
    }
4x
64
65
}
66
67
// MARK: Helper methods where the Context is Any?
68
69
public extension Factory where Context == Any? {
70
71
    /// Builds a `Factory`'s view controller.
72
    func build() throws -> ViewController {
7x
73
        try build(with: nil)
7x
74
    }
7x
75
76
    /// Prepares the `Factory` and builds its `UIViewController`
77
    func execute() throws -> ViewController {
3x
78
        var factory = self
3x
79
        try factory.prepare()
3x
80
        return try factory.build()
3x
81
    }
3x
82
83
}
84
85
// MARK: Helper methods where the Context is Void
86
87
public extension Factory where Context == Void {
88
89
    /// Builds a `Factory`'s view controller.
90
    func build() throws -> ViewController {
1x
91
        try build(with: ())
1x
92
    }
1x
93
94
    /// Prepares the `Factory` and builds its `UIViewController`
95
    func execute() throws -> ViewController {
1x
96
        var factory = self
1x
97
        try factory.prepare()
1x
98
        return try factory.build()
1x
99
    }
1x
100
101
}