Slather logo

Coverage for "UINavigationController+Action.swift" : 88.89%

(48 of 54 relevant lines covered)

RouteComposer/Classes/Actions/UINavigationController+Action.swift

1
//
2
// RouteComposer
3
// UINavigationController+Action.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
// MARK: Actions for UINavigationController
17
18
public extension ContainerViewController where Self: UINavigationController {
19
20
    // MARK: Steps
21
22
    /// Replaces all the child view controllers in the `UINavigationController`'s children stack
23
    static func pushAsRoot() -> NavigationControllerActions.PushAsRootAction<Self> {
3x
24
        NavigationControllerActions.PushAsRootAction()
3x
25
    }
3x
26
27
    /// Pushes a child view controller into the `UINavigationController`'s children stack
28
    static func push() -> NavigationControllerActions.PushAction<Self> {
76x
29
        NavigationControllerActions.PushAction()
76x
30
    }
76x
31
32
    /// Pushes a child view controller, replacing the existing, into the `UINavigationController`'s children stack
33
    static func pushReplacingLast() -> NavigationControllerActions.PushReplacingLastAction<Self> {
5x
34
        NavigationControllerActions.PushReplacingLastAction()
5x
35
    }
5x
36
37
}
38
39
/// Actions for `UINavigationController`
40
public enum NavigationControllerActions {
41
42
    // MARK: Internal entities
43
44
    /// Pushes a view controller into `UINavigationController`'s child stack
45
    public struct PushAction<ViewController: UINavigationController>: ContainerAction {
46
47
        // MARK: Methods
48
49
        /// Constructor
50
        init() {}
76x
51
52
        public func perform(with viewController: UIViewController,
53
                            on navigationController: ViewController,
54
                            animated: Bool,
55
                            completion: @escaping (_: RoutingResult) -> Void) {
21x
56
            navigationController.pushViewController(viewController, animated: animated)
21x
57
            if let transitionCoordinator = navigationController.transitionCoordinator, animated {
21x
58
                transitionCoordinator.animate(alongsideTransition: nil) { _ in
13x
59
                    completion(.success)
13x
60
                }
13x
61
            } else {
21x
62
                completion(.success)
8x
63
            }
21x
64
        }
21x
65
66
    }
67
68
    /// Replaces all the child view controllers in the `UINavigationController`'s child stack
69
    public struct PushAsRootAction<ViewController: UINavigationController>: ContainerAction {
70
71
        // MARK: Methods
72
73
        /// Constructor
74
        init() {}
3x
75
76
        public func perform(embedding viewController: UIViewController,
77
                            in childViewControllers: inout [UIViewController]) {
2x
78
            childViewControllers.removeAll()
2x
79
            childViewControllers.append(viewController)
2x
80
        }
2x
81
82
        public func perform(with viewController: UIViewController,
83
                            on navigationController: ViewController,
84
                            animated: Bool,
85
                            completion: @escaping (_: RoutingResult) -> Void) {
1x
86
            navigationController.setViewControllers([viewController], animated: animated)
1x
87
            if let transitionCoordinator = navigationController.transitionCoordinator, animated {
1x
88
                transitionCoordinator.animate(alongsideTransition: nil) { _ in
!
89
                    completion(.success)
!
90
                }
!
91
            } else {
1x
92
                completion(.success)
1x
93
            }
1x
94
        }
1x
95
96
    }
97
98
    /// Pushes a view controller into the `UINavigationController`'s child stack replacing the last one
99
    public struct PushReplacingLastAction<ViewController: UINavigationController>: ContainerAction {
100
101
        // MARK: Methods
102
103
        /// Constructor
104
        init() {}
5x
105
106
        public func perform(embedding viewController: UIViewController,
107
                            in childViewControllers: inout [UIViewController]) {
5x
108
            if !childViewControllers.isEmpty {
5x
109
                childViewControllers.removeLast()
4x
110
            }
5x
111
            childViewControllers.append(viewController)
5x
112
        }
5x
113
114
        public func perform(with viewController: UIViewController,
115
                            on navigationController: ViewController,
116
                            animated: Bool,
117
                            completion: @escaping (_: RoutingResult) -> Void) {
1x
118
            var viewControllers = navigationController.viewControllers
1x
119
            perform(embedding: viewController, in: &viewControllers)
1x
120
            navigationController.setViewControllers(viewControllers, animated: animated)
1x
121
            if let transitionCoordinator = navigationController.transitionCoordinator, animated {
1x
122
                transitionCoordinator.animate(alongsideTransition: nil) { _ in
!
123
                    completion(.success)
!
124
                }
!
125
            } else {
1x
126
                completion(.success)
1x
127
            }
1x
128
        }
1x
129
130
    }
131
132
}