Slather logo

Coverage for "ContextTask.swift" : 100.00%

(24 of 24 relevant lines covered)

RouteComposer/Classes/ContextTask.swift

1
//
2
// RouteComposer
3
// ContextTask.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 Foundation
14
import UIKit
15
16
/// The task to be applied after a `UIViewController` was created or found.
17
///
18
/// ### NB
19
/// The `ContextTask` will be applied to the new `UIViewController` before it's integration into the stack.
20
public protocol ContextTask {
21
22
    // MARK: Associated types
23
24
    /// A`UIViewController` type associated with this `ContextTask`
25
    associatedtype ViewController: UIViewController
26
27
    /// A Context type associated with this `ContextTask`
28
    associatedtype Context
29
30
    // MARK: Methods to implement
31
32
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
33
    /// be applied to a view controller it should throw an exception.
34
    ///
35
    /// - Parameters:
36
    ///   - context: The `Context` instance provided to the `Router`
37
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
38
    mutating func prepare(with context: Context) throws
39
40
    /// The `Router` will call this method to run the `ContextTask` immediately after `UIViewController` been created
41
    /// or found
42
    ///
43
    /// - Parameters:
44
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
45
    ///   - context: The `Context` instance that was passed to the `Router`
46
    func perform(on viewController: ViewController, with context: Context) throws
47
48
}
49
50
// MARK: Default implementation
51
52
public extension ContextTask {
53
54
    /// Default implementation does nothing
55
    mutating func prepare(with context: Context) throws {}
109x
56
57
}
58
59
// MARK: Helper methods
60
61
public extension ContextTask {
62
63
    /// Prepares the `ContextTask` and executes it
64
    func execute(on viewController: ViewController, with context: Context) throws {
3x
65
        var contextTask = self
3x
66
        try contextTask.prepare(with: context)
3x
67
        try contextTask.perform(on: viewController, with: context)
3x
68
    }
3x
69
70
}
71
72
// MARK: Helper methods where the Context is Any?
73
74
public extension ContextTask where Context == Any? {
75
76
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
77
    /// be applied to a view controller it should throw an exception.
78
    ///
79
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
80
    mutating func prepare() throws {
1x
81
        try prepare(with: nil)
1x
82
    }
1x
83
84
    /// The `Router` will call this method to run the `ContextTask` immediately after `UIViewController` been created
85
    /// or found
86
    ///
87
    /// - Parameters:
88
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
89
    func perform(on viewController: ViewController) throws {
1x
90
        try perform(on: viewController, with: nil)
1x
91
    }
1x
92
93
    /// Prepares the `ContextTask` and executes it
94
    func execute(on viewController: ViewController) throws {
1x
95
        try execute(on: viewController, with: nil)
1x
96
    }
1x
97
98
}
99
100
// MARK: Helper methods where the Context is Void
101
102
public extension ContextTask where Context == Void {
103
104
    /// The `Router` will call this method before the navigation process. If the `ContextTask` is not able to
105
    /// be applied to a view controller it should throw an exception.
106
    ///
107
    /// - Throws: The `RoutingError` if `ContextTask` can't be applied.
108
    mutating func prepare() throws {
1x
109
        try prepare(with: ())
1x
110
    }
1x
111
112
    /// The method that will be called by the `Router` to run `ContextTask` immediately after `UIViewController` been created
113
    /// or found
114
    ///
115
    /// - Parameters:
116
    ///   - viewController: The `UIViewController` instance described in the step that `ContextTask` attached to
117
    func perform(on viewController: ViewController) throws {
1x
118
        try perform(on: viewController, with: ())
1x
119
    }
1x
120
121
    /// Prepares the `ContextTask` and executes it
122
    func execute(on viewController: ViewController) throws {
1x
123
        try execute(on: viewController, with: ())
1x
124
    }
1x
125
126
}