A list of awesome helpers for Swift and iOS
Usage:
extension UIView: Builder {}
lazy var label = UILabel()
.. \.text <- "Hello, World!"
.. \.font <- .systemFont(ofSize: 40)
.. \.textColor <- .white
Implementation:
infix operator ..: AdditionPrecedence
infix operator <-: MultiplicationPrecedence
struct Predicate<Element> {
let code: (Element) -> Element
func runCode(for element: Element) -> Element {
return code(element)
}
}
func <- <Element, T>(_ attribute: WritableKeyPath<Element, T>,
_ constant: T) -> Predicate<Element> {
return Predicate(code: { value in
var copy = value
copy[keyPath: attribute] = constant
return copy
})
}
protocol Builder {}
extension Builder {
@discardableResult
static func .. (_ element: Self,
_ predicate: Predicate<Self>) -> Self {
return element.with(predicate)
}
private func with(_ predicate: Predicate<Self>) -> Self {
return predicate.runCode(for: self)
}
}
- PresentableRouter
- PushableRouter
- TabBarRouter
- TabPageRouter
Usage:
- Make your Router implement
PresentableRouter
final class SomeModalRouter: PresentableRouter {
// ...
}
- Simply call its
start()
method
let router = SomeModalRouter(...)
router.start()
Implementation:
import UIKit
protocol PresentableRouter: ShowableRouter {
var presentingViewController: UIViewController { get }
}
extension PresentableRouter {
func show(viewController: UIViewController, animated: Bool) {
currentViewController = viewController
presentingViewController.present(viewController, animated: animated)
}
}
Obs.: It requires ShowableRouter
and Router
protocols.
Usage:
- Make your Router implement
PushableRouter
final class SomeRouter: PushableRouter {
// ...
}
- Simply call its
start()
method
let router = SomeRouter(...)
router.start()
Implementation:
import UIKit
protocol PushableRouter: ShowableRouter {
var presentingViewController: UINavigationController { get }
}
extension PushableRouter {
func show(viewController: UIViewController, animated: Bool) {
currentViewController = viewController
presentingViewController.pushViewController(viewController, animated: animated)
}
}
Obs.: It requires ShowableRouter
and Router
protocols.
A prerequisite for ShowableRouter
.
Implementation:
import UIKit
protocol Router: class {
var currentViewController: UIViewController? { get }
func start()
func start(animated: Bool)
}
extension Router {
func start() {
start(animated: true)
}
}
A prerequisite for PushableRouter
, PresentableRouter
, RootRouter
and TabPageRouter
Implementation:
import UIKit
protocol ShowableRouter: Router {
var currentViewController: UIViewController? { get set }
func createViewController() -> UIViewController
func show(viewController: UIViewController, animated: Bool)
}
extension ShowableRouter {
func start(animated: Bool = true) {
let viewController = createViewController()
show(viewController: viewController, animated: animated)
}
}
Implementation steps:
- Remove
@UIApplicationMain
fromAppDelegate.swift
- Create a
main.swift
file and add this:
// main.swift
import UIKit
let appDelegateClass: AnyClass =
NSClassFromString("TestsAppDelegate") ?? AppDelegate.self
UIApplicationMain(
CommandLine.argc,
CommandLine.unsafeArgv,
nil,
NSStringFromClass(appDelegateClass)
)
- Create a
TestsAppDelegate.swift
file -- which will be our mock. - Add it to the desired tests target
- Implement it:
import UIKit
@testable import YourProjectName
@objc(TestsAppDelegate)
class TestsAppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// do some testing setup here
return true
}
}