Slather logo

Coverage for "UITabBarController+Action.swift" : 100.00%

(35 of 35 relevant lines covered)

RouteComposer/Classes/Actions/UITabBarController+Action.swift

1
//
2
// RouteComposer
3
// UITabBarController+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 UITabBarController
17
18
public extension ContainerViewController where Self: UITabBarController {
19
20
    // MARK: Steps
21
22
    /// Adds a `UIViewController` to a `UITabBarController`
23
    ///
24
    ///   - tabIndex: index of a tab.
25
    ///   - replacing: should be set to `true` if an existing view controller should be replaced.
26
    ///     If condition has not been passed, a view controller
27
    ///   will be added after the latest one.
28
    static func add(at tabIndex: Int, replacing: Bool = false) -> TabBarControllerActions.AddTabAction<Self> {
8x
29
        TabBarControllerActions.AddTabAction(at: tabIndex, replacing: replacing)
8x
30
    }
8x
31
32
    /// Adds a `UIViewController` to a `UITabBarController`
33
    ///
34
    ///   - tabIndex: index of a tab.
35
    ///     If condition has not been passed, a view controller
36
    ///   will be added after the latest one.
37
    static func add(at tabIndex: Int? = nil) -> TabBarControllerActions.AddTabAction<Self> {
26x
38
        TabBarControllerActions.AddTabAction(at: tabIndex)
26x
39
    }
26x
40
41
}
42
43
/// Actions for `UITabBarController`
44
public enum TabBarControllerActions {
45
46
    // MARK: Internal entities
47
48
    /// Integrates a `UIViewController` in to a `UITabBarController`
49
    public struct AddTabAction<ViewController: UITabBarController>: ContainerAction {
50
51
        // MARK: Properties
52
53
        /// The index of the tab after which one a view controller should be added.
54
        public let tabIndex: Int?
55
56
        /// The flag that tab should be replaced instead.
57
        public let replacing: Bool
58
59
        // MARK: Methods
60
61
        /// Constructor
62
        ///
63
        /// - Parameters:
64
        ///   - tabIndex: index of the tab after which one a view controller should be added.
65
        ///   - replacing: instead of adding a view controller after the tabIndex - replace the one at that index.
66
        init(at tabIndex: Int, replacing: Bool = false) {
8x
67
            self.tabIndex = tabIndex
8x
68
            self.replacing = replacing
8x
69
        }
8x
70
71
        /// Constructor
72
        ///
73
        ///   - tabIndex: index of the tab after which one a view controller should be added.
74
        ///     If has not been passed - a view controller
75
        ///   will be added after the latest one.
76
        init(at tabIndex: Int? = nil) {
26x
77
            self.tabIndex = tabIndex
26x
78
            self.replacing = false
26x
79
        }
26x
80
81
        public func perform(embedding viewController: UIViewController,
82
                            in childViewControllers: inout [UIViewController]) {
22x
83
            setup(viewController: viewController, at: &childViewControllers, tabIndex: tabIndex)
22x
84
        }
22x
85
86
        public func perform(with viewController: UIViewController,
87
                            on tabBarController: ViewController,
88
                            animated: Bool,
89
                            completion: @escaping (_: RoutingResult) -> Void) {
5x
90
            var tabViewControllers = tabBarController.viewControllers ?? []
5x
91
            setup(viewController: viewController, at: &tabViewControllers, tabIndex: tabIndex)
5x
92
            tabBarController.setViewControllers(tabViewControllers, animated: animated)
5x
93
5x
94
            completion(.success)
5x
95
        }
5x
96
97
        private func setup(viewController: UIViewController,
98
                           at childViewControllers: inout [UIViewController], tabIndex: Int?) {
27x
99
            if let tabIndex, tabIndex < childViewControllers.count {
27x
100
                if replacing {
6x
101
                    childViewControllers[tabIndex] = viewController
4x
102
                } else {
6x
103
                    childViewControllers.insert(viewController, at: tabIndex)
2x
104
                }
6x
105
            } else {
27x
106
                childViewControllers.append(viewController)
21x
107
            }
27x
108
        }
27x
109
110
    }
111
112
}