|
import UIKit |
|
|
|
protocol NavigationCoordinator: AnyObject { |
|
|
|
/// - Returns: true if it successfully completed the navigation |
|
@discardableResult func navigate(from source: UIViewController, |
|
to destination: UIViewController.Type, |
|
data: NavigationData?) -> Bool |
|
} |
|
|
|
/// Data structure used to simplify the passing of data. |
|
struct NavigationData { |
|
private var rawData: [String: Any] = [:] |
|
|
|
/// Key values. |
|
init(_ values: [String: Any]) { |
|
rawData = values |
|
} |
|
|
|
/// Use this constructor when all the values have different types. |
|
/// |
|
/// let data = NavigationData(IndexPath(row: 1, section: 2), "james") |
|
/// let indexPath: IndexPath? = data.get() |
|
/// let username = data.get(String.self) |
|
init(_ values: Any...) { |
|
values.forEach({ rawData[UUID().uuidString] = $0 }) |
|
} |
|
|
|
init(build: (Builder) -> Void) { |
|
let builder = Builder() |
|
|
|
build(builder) |
|
|
|
rawData = builder.rawData |
|
} |
|
|
|
/// Retrieve the value of implicit type T associated with *key*. |
|
/// |
|
/// let token: String? = data.get(key: "token") |
|
func get<T>(key: String) -> T? { |
|
return rawData[key] as? T |
|
} |
|
|
|
/// Retrieve the value of type *dataType* associated with *key*. |
|
/// |
|
/// let token = data.get(key: "token", String.self) |
|
func get<T>(key: String, _ dataType: T.Type) -> T? { |
|
return get(key: key) as T? |
|
} |
|
|
|
/// Retrieve the first value of implicit type T. |
|
/// |
|
/// let token: String? = data.get() |
|
func get<T>() -> T? { |
|
return rawData.values.first(where: { $0 is T }) as? T |
|
} |
|
|
|
/// Retrieve the first value of type *dataType*. |
|
/// |
|
/// let token = data.get(String.self) |
|
func get<T>(_ dataType: T.Type) -> T? { |
|
return rawData.values.first(where: { type(of: $0) == dataType }) as? T |
|
} |
|
|
|
class Builder { |
|
fileprivate var rawData: [String: Any] = [:] |
|
|
|
func add(key: String, data: Any) { |
|
rawData[key] = data |
|
} |
|
|
|
/// Only use this method when all the data have different types. |
|
/// |
|
/// - Parameter data: any data |
|
func add(data: Any) { |
|
rawData[UUID().uuidString] = data |
|
} |
|
} |
|
} |