Slather logo

Coverage for "RouteComposerDefaults.swift" : 87.23%

(41 of 47 relevant lines covered)

RouteComposer/Classes/RouteComposerDefaults.swift

1
//
2
// RouteComposer
3
// RouteComposerDefaults.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
15
private let lock = NSObject()
16
17
/// Default configuration for all the instances in `RouteComposer`.
18
///
19
/// **NB:** If you are going to provide your own defaults, make sure that `RouteComposerDefaults.configureWith(...)` is called
20
/// before the instantiation of any other `RouteComposer`'s instances. `AppDelegate` is probably the best place for it.
21
public final class RouteComposerDefaults {
22
23
    // MARK: Properties
24
25
    /// Singleton access.
26
    public static var shared: RouteComposerDefaults = {
14x
27
        objc_sync_enter(lock)
14x
28
        defer {
14x
29
            objc_sync_exit(lock)
14x
30
            configurationStorage?.logInstantiation()
14x
31
        }
14x
32
        switch configurationStorage {
14x
33
        case let .some(configurationStorage):
14x
34
            return configurationStorage
14x
35
        case .none:
14x
36
            let buildInDefaults = RouteComposerDefaults()
!
37
            configurationStorage = buildInDefaults
!
38
            return buildInDefaults
!
39
        }
14x
40
    }()
14x
41
42
    /// Default `Logger` instance.
43
    public private(set) var logger: Logger?
44
45
    /// Default `ContainerAdapterLocator` instance.
46
    public private(set) var containerAdapterLocator: ContainerAdapterLocator
47
48
    /// Default `StackIterator` instance.
49
    public private(set) var stackIterator: StackIterator
50
51
    /// Default `WindowProvider` instance.
52
    public private(set) var windowProvider: WindowProvider
53
54
    private static var configurationStorage: RouteComposerDefaults?
55
56
    // MARK: Methods
57
58
    /// Default configuration for all the instances in `RouteComposer`.
59
    ///
60
    /// **NB:** If you are going to provide your own defaults, make sure that `RouteComposerDefaults.configureWith(...)` is called
61
    /// before the instantiation of any other `RouteComposer`'s instances. `AppDelegate` is probably the best place for it.
62
    /// - Parameters:
63
    ///   - logger: Default `Logger` instance.
64
    ///   - windowProvider: Default `WindowProvider` instance.
65
    ///   - containerAdapterLocator: Default `ContainerAdapterLocator` instance.
66
    ///   - stackIterator: Default `StackIterator` instance.
67
    public class func configureWith(logger: Logger? = DefaultLogger(.warnings),
68
                                    windowProvider: WindowProvider = KeyWindowProvider(),
69
                                    containerAdapterLocator: ContainerAdapterLocator = DefaultContainerAdapterLocator(),
70
                                    stackIterator: StackIterator? = nil) {
14x
71
        objc_sync_enter(lock)
14x
72
        defer {
14x
73
            objc_sync_exit(lock)
14x
74
        }
14x
75
        guard configurationStorage == nil else {
14x
76
            assertionFailure("Default values were initialised once. \(#function) must be called before any RouteComposer instantiation!")
!
77
            return
!
78
        }
14x
79
        configurationStorage = RouteComposerDefaults(logger: logger,
14x
80
                                                     windowProvider: windowProvider,
14x
81
                                                     containerAdapterLocator: containerAdapterLocator,
14x
82
                                                     stackIterator: stackIterator)
14x
83
    }
14x
84
85
    private init(logger: Logger? = DefaultLogger(.warnings),
86
                 windowProvider: WindowProvider = KeyWindowProvider(),
87
                 containerAdapterLocator: ContainerAdapterLocator = DefaultContainerAdapterLocator(),
88
                 stackIterator: StackIterator? = nil) {
14x
89
        self.logger = logger
14x
90
        self.windowProvider = windowProvider
14x
91
        self.containerAdapterLocator = containerAdapterLocator
14x
92
        self.stackIterator = stackIterator ?? DefaultStackIterator(windowProvider: windowProvider, containerAdapterLocator: containerAdapterLocator)
14x
93
    }
14x
94
95
    private func logInstantiation() {
14x
96
        guard let logger else {
14x
97
            return
!
98
        }
14x
99
        logger.log(.info("""
14x
100
        Initialised defaults values with:
14x
101
            Logger: \(logger)
14x
102
            WindowProvider: \(windowProvider)
14x
103
            ContainerAdapterLocator: \(containerAdapterLocator)
14x
104
            StackIterator:\(stackIterator)
14x
105
        """))
14x
106
    }
14x
107
108
}