Slather logo

Coverage for "NavigationControllerAdapter.swift" : 94.44%

(51 of 54 relevant lines covered)

RouteComposer/Classes/Adapters/NavigationControllerAdapter.swift

1
//
2
// RouteComposer
3
// NavigationControllerAdapter.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
/// Default `ContainerAdapter` for `UINavigationController`
17
public struct NavigationControllerAdapter<VC: UINavigationController>: ConcreteContainerAdapter {
18
19
    // MARK: Properties
20
21
    weak var navigationController: VC?
22
23
    // MARK: Methods
24
25
    public init(with navigationController: VC) {
441x
26
        self.navigationController = navigationController
441x
27
    }
441x
28
29
    public var containedViewControllers: [UIViewController] {
223x
30
        navigationController?.viewControllers ?? []
223x
31
    }
223x
32
33
    public var visibleViewControllers: [UIViewController] {
432x
34
        guard let topViewController = navigationController?.topViewController else {
432x
35
            return []
1x
36
        }
431x
37
        return [topViewController]
431x
38
    }
432x
39
40
    public func makeVisible(_ viewController: UIViewController, animated: Bool, completion: @escaping (_: RoutingResult) -> Void) {
25x
41
        guard let navigationController else {
25x
42
            completion(.failure(RoutingError.compositionFailed(.init("\(String(describing: VC.self)) has been deallocated"))))
1x
43
            return
1x
44
        }
24x
45
        guard navigationController.topViewController != viewController else {
24x
46
            completion(.success)
1x
47
            return
1x
48
        }
23x
49
        guard contains(viewController) else {
23x
50
            completion(.failure(RoutingError.compositionFailed(.init("\(String(describing: navigationController)) does not contain \(String(describing: viewController))"))))
2x
51
            return
2x
52
        }
21x
53
        navigationController.popToViewController(viewController, animated: animated)
21x
54
        if let transitionCoordinator = navigationController.transitionCoordinator, animated {
21x
55
            transitionCoordinator.animate(alongsideTransition: nil) { _ in
16x
56
                if navigationController.isViewLoaded {
16x
57
                    navigationController.view.layoutIfNeeded()
16x
58
                }
16x
59
                completion(.success)
16x
60
            }
16x
61
        } else {
21x
62
            if navigationController.isViewLoaded {
5x
63
                navigationController.view.layoutIfNeeded()
5x
64
            }
5x
65
            completion(.success)
5x
66
        }
21x
67
    }
21x
68
69
    public func setContainedViewControllers(_ containedViewControllers: [UIViewController], animated: Bool, completion: @escaping (_: RoutingResult) -> Void) {
3x
70
        guard let navigationController else {
3x
71
            completion(.failure(RoutingError.compositionFailed(.init("\(String(describing: VC.self)) has been deallocated"))))
1x
72
            return
1x
73
        }
2x
74
        navigationController.setViewControllers(containedViewControllers, animated: animated)
2x
75
        if let transitionCoordinator = navigationController.transitionCoordinator, animated {
2x
76
            transitionCoordinator.animate(alongsideTransition: nil) { _ in
!
77
                completion(.success)
!
78
            }
!
79
        } else {
2x
80
            completion(.success)
2x
81
        }
2x
82
    }
2x
83
84
}