Best Mockingbird code snippet using UIViewController
TransitionBehavior.swift
Source:TransitionBehavior.swift  
...9// MARK: Application based10/// application root, application present11public protocol ApplicationBasedTransitionBehavior {12    func isAvailable(in application: UIApplication) -> Bool13    func perform<To: UIViewController>(in application: UIApplication, to viewController: To, animated: Bool)14}15public extension UIApplication {16    func isAvailable(transition: ApplicationBasedTransitionBehavior) -> Bool {17        return transition.isAvailable(in: self)18    }19    20    func perform<To: UIViewController>(transition: ApplicationBasedTransitionBehavior, to viewController: To, animated: Bool) {21        return transition.perform(in: self, to: viewController, animated: animated)22    }23    24    @discardableResult25    func perform<To: UIViewController>(transitionIfAvailable transition: ApplicationBasedTransitionBehavior, to viewController: To, animated: Bool) -> Bool {26        guard isAvailable(transition: transition) else { return false }27        28        perform(transition: transition, to: viewController, animated: animated)29        return true30    }31}32public extension UIApplication {33    func perform(presetTransition transition: ApplicationBasedTransition, to viewController: UIViewController, animated: Bool) {34        perform(transition: transition, to: viewController, animated: animated)35    }36}37public struct ApplicationBasedTransition: ApplicationBasedTransitionBehavior {38    let base: ApplicationBasedTransitionBehavior39    40    public func isAvailable(in application: UIApplication) -> Bool {41        return base.isAvailable(in: application)42    }43    44    public func perform<To>(in application: UIApplication, to viewController: To, animated: Bool) where To : UIViewController {45        base.perform(in: application, to: viewController, animated: animated)46    }47    48    public static let root = ApplicationBasedTransition(base: Root())49    struct Root: ApplicationBasedTransitionBehavior {50        func isAvailable(in application: UIApplication) -> Bool {51            return UIApplication.shared.delegate?.window != nil52        }53        54        func perform<To>(in application: UIApplication, to viewController: To, animated: Bool) where To : UIViewController {55            let window = UIApplication.shared.delegate!.window!!56            if let _ = window.rootViewController?.presentedViewController {57                window.rootViewController?.dismiss(animated: animated, completion: {58                    window.rootViewController = viewController59                    window.makeKeyAndVisible()60                })61            } else {62                window.rootViewController = viewController63                window.makeKeyAndVisible()64            }65        }66    }67    68    // TODO: Wrap ViewControllerBasedTransition`s as ApplicationBased ? 69    public static let present = ApplicationBasedTransition(base: Present())70    struct Present: ApplicationBasedTransitionBehavior {71        func isAvailable(in application: UIApplication) -> Bool {72            return UIApplication.shared.delegate?.window??.rootViewController != nil73        }74        75        func perform<To>(in application: UIApplication, to viewController: To, animated: Bool) where To : UIViewController {76            let rootViewController = UIApplication.shared.delegate!.window!!.rootViewController!77            rootViewController.present(viewController, animated: animated)78        }79    }80}81struct AnyApplicationBasedTransitionBehavior: ApplicationBasedTransitionBehavior {82    typealias TransitionAvailable<In: UIApplication> = (In) -> Bool83    typealias TransitionAction<In: UIApplication, To: UIViewController> = (In, To, Bool) -> Void84    private let available: TransitionAvailable<UIApplication>85    private let action: TransitionAction<UIApplication, UIViewController>86    87    init(available: @escaping TransitionAvailable<UIApplication>, action: @escaping TransitionAction<UIApplication, UIViewController>) {88        self.available = available89        self.action = action90    }91    92    func isAvailable(in application: UIApplication) -> Bool {93        return available(application)94    }95    96    func perform<To>(in application: UIApplication, to viewController: To, animated: Bool) where To : UIViewController {97        action(application, viewController, animated)98    }99}100// MARK: ViewController based101// TODO: Add preview behavior - UIViewControllerPreviewing102// TODO: Implement isAvailable by one agreement, or add yet method for evaluate state for ready103// TODO: Remove 'to viewControllers' parameter from main function, use it in concrete behavior104/// push (replace, navigationRoot), present, preview105public protocol ViewControllerBasedTransitionBehavior {106    associatedtype Source: UIViewController107    associatedtype Target: UIViewController108    func isAvailable(in sourceViewController: Source) -> Bool109    func perform(in sourceViewController: Source, to viewControllers: [Target], animated: Bool)110}111// TODO: Remove this extension after Apple fixed bug with convert array to variadic parameters112extension ViewControllerBasedTransitionBehavior {113    func perform(in sourceViewController: Source, to viewControllers: Target ..., animated: Bool) {114        perform(in: sourceViewController, to: viewControllers, animated: animated)115    }116}117public protocol PresentConfiguration {118    func isAvailable(in viewController: UIViewController) -> Bool119    func prepare(forPresent controller: UIViewController)120}121public struct ViewControllerBasedTransition<Source: UIViewController, Target: UIViewController>: ViewControllerBasedTransitionBehavior {122    fileprivate typealias This = ViewControllerBasedTransition123    let isAvailable: (Source) -> Bool124    let action: (Source, [Target], Bool) -> Void125    126    init<T: ViewControllerBasedTransitionBehavior>(base: T) where T.Source == Source, T.Target == Target {127        isAvailable = base.isAvailable128        action = base.perform129    }130    131    public func isAvailable(in sourceViewController: Source) -> Bool {132        return isAvailable(sourceViewController)133    }134    135    public func perform(in sourceViewController: Source, to viewControllers: [Target], animated: Bool) {136        action(sourceViewController, viewControllers, animated)137    }138}139// MARK: ViewControllerBased - UIViewController140extension ViewControllerBasedTransition {141    public static func addChilds(layout: ((UIView, [UIView]) -> Void)? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {142        return .init(base: AddChilds(layout: layout))143    }144    /// Add child view controller to source view controller, with define layout.145    struct AddChilds: ViewControllerBasedTransitionBehavior {146        let layout: ((UIView, [UIView]) -> Void)?147        func isAvailable(in sourceViewController: UIViewController) -> Bool {148            return true149        }150        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {151            viewControllers.forEach { viewController in152                sourceViewController.addChild(viewController)153                sourceViewController.view.addSubview(viewController.view)154                viewController.didMove(toParent: sourceViewController)155            }156            layout?(sourceViewController.view, viewControllers.map { $0.view })157        }158    }159    public static var removeChilds: ViewControllerBasedTransition<UIViewController, UIViewController> {160        return .init(base: RemoveChilds())161    }162    163    /// Remove child view controller from source view controller.164    struct RemoveChilds: ViewControllerBasedTransitionBehavior {165        func isAvailable(in sourceViewController: UIViewController) -> Bool {166            return sourceViewController.children.count > 0167        }168        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {169            let removed = viewControllers.count > 0 ? viewControllers : sourceViewController.children170            removed.forEach { viewController in171                viewController.willMove(toParent: nil)172                viewController.view.removeFromSuperview()173                viewController.removeFromParent()174            }175        }176    }177}178// MARK: ViewControllerBased - UINavigationController179extension ViewControllerBasedTransition {180    struct AnyChildNavigation<T: ViewControllerBasedTransitionBehavior>: ViewControllerBasedTransitionBehavior where T.Source == UINavigationController {181        let navigationBehavior: T182        183        func isAvailable(in sourceViewController: UIViewController) -> Bool {184            return sourceViewController.navigationController.map { navigationBehavior.isAvailable(in: $0) } ?? false185        }186        func perform(in sourceViewController: UIViewController, to viewControllers: [T.Target], animated: Bool) {187            navigationBehavior.perform(in: sourceViewController.navigationController!, to: viewControllers, animated: animated)188        }189    }190    191    public static var push: ViewControllerBasedTransition<UINavigationController, UIViewController> {192        return .init(base: Push())193    }194    struct Push: ViewControllerBasedTransitionBehavior {195        func isAvailable(in sourceViewController: UINavigationController) -> Bool {196            return true197        }198        199        func perform(in sourceViewController: UINavigationController, to viewController: [UIViewController], animated: Bool) {200            sourceViewController.setViewControllers(sourceViewController.viewControllers + viewController,201                                                    animated: true)202        }203    }204    public static var navigationPush: ViewControllerBasedTransition<UIViewController, UIViewController> {205        return .init(base: AnyChildNavigation(navigationBehavior: This.push))206    }207    /* Uncomment if require additional behavior instead AnyChildNavigation208    struct ChildPush: ViewControllerBasedTransitionBehavior {209        let navigationPush: Push210        func isAvailable(in sourceViewController: UIViewController) -> Bool {211            return sourceViewController.navigationController.map { navigationPush.isAvailable(in: $0) } ?? false212        }213        214        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {215            navigationPush.perform(in: sourceViewController.navigationController!, to: viewControllers, animated: animated)216        }217    }218     */219    220    public static func pop(popped: UnsafeMutablePointer<UIViewController?>? = nil) -> ViewControllerBasedTransition<UINavigationController, UIViewController> {221        return .init(base: Pop(popped: popped))222    }223    public static func popToRoot(popped: UnsafeMutablePointer<[UIViewController]?>? = nil) -> ViewControllerBasedTransition<UINavigationController, UIViewController> {224        return .init(base: Pop.Root(popped: popped))225    }226    public static func popTo(popped: UnsafeMutablePointer<[UIViewController]?>? = nil) -> ViewControllerBasedTransition<UINavigationController, UIViewController> {227        return .init(base: Pop.To(popped: popped))228    }229    public static func pop(back: Int, popped: UnsafeMutablePointer<[UIViewController]?>? = nil) -> ViewControllerBasedTransition<UINavigationController, UIViewController> {230        return .init(base: Pop.Back(back: back, popped: popped))231    }232    struct Pop: ViewControllerBasedTransitionBehavior {233        let popped: UnsafeMutablePointer<UIViewController?>?234        func isAvailable(in sourceViewController: UINavigationController) -> Bool {235            return sourceViewController.viewControllers.count > 0236        }237        func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {238            popped?.pointee = sourceViewController.popViewController(animated: animated)239        }240        struct To: ViewControllerBasedTransitionBehavior {241            let popped: UnsafeMutablePointer<[UIViewController]?>?242            func isAvailable(in sourceViewController: UINavigationController) -> Bool {243                return sourceViewController.viewControllers.count > 1244            }245            func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {246                popped?.pointee = sourceViewController.popToViewController(viewControllers.first!, animated: animated)247            }248        }249        struct Back: ViewControllerBasedTransitionBehavior {250            let back: Int251            let popped: UnsafeMutablePointer<[UIViewController]?>?252            func isAvailable(in sourceViewController: UINavigationController) -> Bool {253                return sourceViewController.viewControllers.count >= back254            }255            func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {256                let stack = sourceViewController.viewControllers257                sourceViewController.setViewControllers(Array(stack.dropLast(back)), animated: animated)258                popped?.pointee = Array(stack.suffix(back))259            }260        }261        struct Root: ViewControllerBasedTransitionBehavior {262            let popped: UnsafeMutablePointer<[UIViewController]?>?263            func isAvailable(in sourceViewController: UINavigationController) -> Bool {264                return true265            }266            func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {267                popped?.pointee = sourceViewController.popToRootViewController(animated: animated)268            }269        }270    }271    public static func navigationPop(popped: UnsafeMutablePointer<UIViewController?>? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {272        return .init(base: AnyChildNavigation(navigationBehavior: This.pop(popped: popped)))273    }274    public static func navigationPop(back: Int, popped: UnsafeMutablePointer<[UIViewController]?>? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {275        return .init(base: AnyChildNavigation(navigationBehavior: This.pop(back: back, popped: popped)))276    }277    public static func navigationPopToRoot(popped: UnsafeMutablePointer<[UIViewController]?>? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {278        return .init(base: AnyChildNavigation(navigationBehavior: This.popToRoot(popped: popped)))279    }280    281    // TODO: After transition to Swift 4, implement replace with range limited by one side282    public static var replace: ViewControllerBasedTransition<UINavigationController, UIViewController> {283        return .replace(last: 1)284    }285    public static func replace(last: Int) -> ViewControllerBasedTransition<UINavigationController, UIViewController> {286        return .init(base: Replace(last: last))287    }288    struct Replace: ViewControllerBasedTransitionBehavior {289        let last: Int290        291        func isAvailable(in sourceViewController: UINavigationController) -> Bool {292            return sourceViewController.viewControllers.count >= last293        }294        295        func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {296            let stack = sourceViewController.viewControllers297            sourceViewController.setViewControllers(stack.dropLast(last) + viewControllers,298                                                    animated: animated)299        }300    }301    public static var navigationReplace: ViewControllerBasedTransition<UIViewController, UIViewController> {302        return .init(base: AnyChildNavigation(navigationBehavior: This.replace))303    }304    public static func navigationReplace(last: Int) -> ViewControllerBasedTransition<UIViewController, UIViewController> {305        return .init(base: AnyChildNavigation(navigationBehavior: This.replace(last: last)))306    }307    /* Uncomment if require additional behavior instead AnyChildNavigation308    struct ChildReplace: ViewControllerBasedTransitionBehavior {309        let navigationReplace: Replace310        311        func isAvailable(in sourceViewController: UIViewController) -> Bool {312            return sourceViewController.navigationController.map { navigationReplace.isAvailable(in: $0) } ?? false313        }314        315        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {316            navigationReplace.perform(in: sourceViewController.navigationController!, to: viewControllers, animated: true)317        }318    }319     */320    321    public static var root: ViewControllerBasedTransition<UINavigationController, UIViewController> {322        return .init(base: Root())323    }324    struct Root: ViewControllerBasedTransitionBehavior {325        func isAvailable(in sourceViewController: UINavigationController) -> Bool {326            return true327        }328        329        func perform(in sourceViewController: UINavigationController, to viewControllers: [UIViewController], animated: Bool) {330            sourceViewController.setViewControllers(viewControllers, animated: animated)331        }332    }333    public static var navigationRoot: ViewControllerBasedTransition<UIViewController, UIViewController> {334        return .init(base: AnyChildNavigation(navigationBehavior: This.root))335    }336    /* Uncomment if require additional behavior instead AnyChildNavigation337    struct NavigationRoot: ViewControllerBasedTransitionBehavior {338        let navigationRoot: Root339        func isAvailable(in sourceViewController: UIViewController) -> Bool {340            return sourceViewController.navigationController.map { navigationRoot.isAvailable(in: $0) } ?? false341        }342        343        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {344            navigationRoot.perform(in: sourceViewController.navigationController!, to: viewControllers, animated: animated)345        }346    }347     */348}349// MARK: ViewControllerBased - Presentation350extension ViewControllerBasedTransition {351    public static var present: ViewControllerBasedTransition<UIViewController, UIViewController> {352        return .present(as: .common(modalStyle: .fullScreen, transitionStyle: .coverVertical))353    }354    public static func present(as configured: Present.Config, completion: (() -> Void)? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {355        return .init(base: Present(config: configured, completion: completion))356    }357    public struct Present: ViewControllerBasedTransitionBehavior {358        let config: Config359        let completion: (() -> Void)?360        361        public func isAvailable(in sourceViewController: UIViewController) -> Bool {362            return sourceViewController.presentedViewController != nil && config.isAvailable(in: sourceViewController)363        }364        365        public func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {366            config.prepare(forPresent: viewControllers.first!)367            sourceViewController.present(viewControllers.first!, animated: animated, completion: completion)368        }369        370        public struct Config: PresentConfiguration {371            let base: PresentConfiguration372            373            public func isAvailable(in viewController: UIViewController) -> Bool {374                return base.isAvailable(in: viewController)375            }376            377            public func prepare(forPresent controller: UIViewController) {378                base.prepare(forPresent: controller)379            }380            381            public static func common(modalStyle: UIModalPresentationStyle, transitionStyle: UIModalTransitionStyle) -> Config {382                return Config(base: Common(modalStyle: modalStyle, transitionStyle: transitionStyle))383            }384            struct Common: PresentConfiguration {385                let modalStyle: UIModalPresentationStyle386                let transitionStyle: UIModalTransitionStyle387                388                func isAvailable(in viewController: UIViewController) -> Bool {389                    // TODO: add checkers390                    guard transitionStyle == .partialCurl,391                        viewController.isBeingPresented,392                        viewController.modalPresentationStyle != .fullScreen else {393                            return true394                    }395                    396                    return false397                }398                399                func prepare(forPresent controller: UIViewController) {400                    controller.modalPresentationStyle = modalStyle401                    controller.modalTransitionStyle = transitionStyle402                }403            }404            405            public static func popover(config: @escaping (UIPopoverPresentationController) -> Void) -> Config {406                return Config(base: Popover(config: config))407            }408            struct Popover: PresentConfiguration {409                let config: (UIPopoverPresentationController) -> Void410                411                func isAvailable(in viewController: UIViewController) -> Bool {412                    return UIDevice.current.userInterfaceIdiom != .phone413                }414                415                func prepare(forPresent controller: UIViewController) {416                    controller.modalPresentationStyle = .popover417                    config(controller.popoverPresentationController!)418                }419            }420            421            public static func custom(delegate: UIViewControllerTransitioningDelegate) -> Config {422                return Config(base: Custom(delegate: delegate))423            }424            struct Custom: PresentConfiguration {425                let delegate: UIViewControllerTransitioningDelegate426                427                func isAvailable(in viewController: UIViewController) -> Bool {428                    return true // TODO: Change?, custom always available429                }430                431                func prepare(forPresent controller: UIViewController) {432                    controller.modalPresentationStyle = .custom433                    controller.transitioningDelegate = delegate434                }435            }436        }437    }438    439    public static func dismiss(completion: (() -> Void)? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {440        return .init(base: Dismiss(completion: completion))441    }442    public static func dismissParent(on level: Int, completion: (() -> Void)? = nil) -> ViewControllerBasedTransition<UIViewController, UIViewController> {443        return .init(base: Dismiss.Parent(level: level, completion: completion))444    }445    struct Dismiss: ViewControllerBasedTransitionBehavior {446        let completion: (() -> Void)?447        func isAvailable(in sourceViewController: UIViewController) -> Bool {448            return sourceViewController.presentedViewController != nil || sourceViewController.presentingViewController != nil449        }450        func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {451            sourceViewController.dismiss(animated: animated, completion: completion)452        }453        struct Parent: ViewControllerBasedTransitionBehavior {454            let level: Int455            let completion: (() -> Void)?456            func isAvailable(in sourceViewController: UIViewController) -> Bool {457                return sourceViewController.hasPresentingViewController(on: level)458            }459            func perform(in sourceViewController: UIViewController, to viewControllers: [UIViewController], animated: Bool) {460                sourceViewController461                    .presentingViewController(on: level)?462                    .dismiss(animated: animated, completion: completion)463            }464        }465    }466}467// MARK: ViewControllerBased - UITabBarController468extension ViewControllerBasedTransition {469    public static func addRemove(added: IndexSet = [], removed: IndexSet = []) -> ViewControllerBasedTransition<UITabBarController, UIViewController> {470        return .init(base: TabBarAddRemove(addRemove: .init(added: added, removed: removed)))471    }472    473    struct TabBarAddRemove: ViewControllerBasedTransitionBehavior {474        let addRemove: AddRemove475        struct AddRemove {476            let added: IndexSet477            let removed: IndexSet478            479            func isConsistent<T>(with source: [T], addedEntities: [T]) -> Bool {480                guard isConsistentRemoved(source: source) else { return false }481                guard added.count == addedEntities.count else { return false }482                guard added.count > 0 else { return true }483                guard added.last! <= source.count else {484                    var prev = source.count485                    while let next = added.integerGreaterThan(prev) {486                        guard prev == next - 1 else {487                            return false488                        }489                        prev = next490                    }491                    return true492                }493                494                return true495            }496            497            func isConsistentRemoved<T>(source: [T]) -> Bool {498                guard let max = removed.last else { return true }499                500                return source.endIndex >= max501            }502            503            func apply<T>(for array: [T], added entities: [T]) -> [T] {504                var array = array505                removed.reversed().forEach { array.remove(at: $0) }506                var iterator = entities.makeIterator()507                added.forEach { array.insert(iterator.next()!, at: $0) }508                509                return array510            }511        }512        513        func isAvailable(in sourceViewController: UITabBarController) -> Bool {514            return true515        }516        517        func perform(in sourceViewController: UITabBarController, to viewControllers: [UIViewController], animated: Bool) {518            let controllers = sourceViewController.viewControllers!519            guard addRemove.isConsistent(with: controllers, addedEntities: viewControllers) else { return }520            521            sourceViewController.setViewControllers(addRemove.apply(for: controllers, added: viewControllers),522                                                    animated: animated)523        }524    }525    526    public static func tabBarAddRemove(added: IndexSet = [], removed: IndexSet = []) -> ViewControllerBasedTransition<UIViewController, UIViewController> {527        return .init(base: AnyChildTabBar(tabBarBehavior: This.addRemove(added: added, removed: removed)))528    }529    struct AnyChildTabBar<T: ViewControllerBasedTransitionBehavior>: ViewControllerBasedTransitionBehavior where T.Source == UITabBarController {530        let tabBarBehavior: T531        532        func isAvailable(in sourceViewController: UIViewController) -> Bool {533            return sourceViewController.tabBarController.map { tabBarBehavior.isAvailable(in: $0) } ?? false534        }535        536        func perform(in sourceViewController: UIViewController, to viewControllers: [T.Target], animated: Bool) {537            tabBarBehavior.perform(in: sourceViewController.tabBarController!, to: viewControllers, animated: animated)538        }539    }540}541// MARK: UIViewController - Extensions542public extension UIViewController {543    func isAvailable<T: ViewControllerBasedTransitionBehavior>(transition: T) -> Bool {544        return transition.isAvailable(in: self as! T.Source)545    }546    547    func perform<T: ViewControllerBasedTransitionBehavior>(transition: T, to viewControllers: [T.Target], animated: Bool) {548        transition.perform(in: self as! T.Source,549                           to: viewControllers,550                           animated: animated)551    }552}553public extension UIViewController {554    func perform(presetTransition transition: ViewControllerBasedTransition<UIViewController, UIViewController>, to viewControllers: UIViewController? ..., animated: Bool) {555        transition.perform(in: self, to: viewControllers.compactMap { $0 }, animated: animated)556    }557    558    @discardableResult559    func perform(presetTransitionIfAvailable transition: ViewControllerBasedTransition<UIViewController, UIViewController>, to viewControllers: UIViewController? ..., animated: Bool, reserved: (ViewControllerBasedTransition<UIViewController, UIViewController>, Bool)) -> Bool {560        let to = viewControllers.compactMap { $0 }561        guard isAvailable(transition: transition) else {562            perform(transition: reserved.0, to: to, animated: reserved.1)563            return false564        }565        566        perform(transition: transition, to: to, animated: animated)567        return true568    }569}570public extension UINavigationController {571    func perform(navigationTransition transition: ViewControllerBasedTransition<UINavigationController, UIViewController>, to viewControllers: UIViewController? ..., animated: Bool) {572        transition.perform(in: self, to: viewControllers.compactMap { $0 }, animated: animated)573    }574}575public extension UITabBarController {576    func perform(tabBarTransition transition: ViewControllerBasedTransition<UITabBarController, UIViewController>, to viewControllers: UIViewController? ..., animated: Bool) {577        transition.perform(in: self, to: viewControllers.compactMap { $0 }, animated: animated)578    }579}580// MARK: Undepended581public struct AnyViewControllerBasedTransitionBehavior<S: UIViewController, T: UIViewController>: ViewControllerBasedTransitionBehavior {582    public typealias TransitionAvailable = (Source) -> Bool583    public typealias TransitionAction = (Source, [Target], Bool) -> Void584    585    private let available: TransitionAvailable586    private let action: TransitionAction587    588    public init(available: @escaping TransitionAvailable, action: @escaping TransitionAction) {589        self.available = available590        self.action = action591    }592    593    public func isAvailable(in sourceViewController: S) -> Bool {594        return available(sourceViewController)595    }...Effect+UIViewController.swift
Source:Effect+UIViewController.swift  
1//2//  Effect+UIViewController.swift3//  Geppetto4//5//  Created by jinseo on 2020/12/02.6//  Copyright © 2020 rinndash. All rights reserved.7//8import UIKit9import RxSwift10import RxCocoa11public extension ReaderType where Value: PrimitiveSequenceType, Value.Trait == SingleTrait, Value.Element == UIViewController {12    var topMost: Effect<Env, UIViewController?> {13        mapT { UIViewController.topMost(of: $0) }14    }15    16    func alert(style: UIAlertController.Style, title: String? = nil, description: String? = nil, buttons: [(String, UIAlertAction.Style)]) -> Effect<Env, String> {17        flatMapT { (vc: UIViewController) -> Effect<Env, String> in18            Effect<Env, String> { (_: Env) -> Single<String> in19                Single<String>.create { [weak vc] single in20                    let alertController = UIAlertController(title: title, message: description, preferredStyle: style)21                    let actions: [UIAlertAction] = buttons.map { buttonTitle, buttonStyle -> UIAlertAction in22                        UIAlertAction(title: buttonTitle, style: buttonStyle, handler: { _ in23                            single(.success(buttonTitle))24                        })25                    }26                    actions.forEach(alertController.addAction)27                    vc?.present(alertController, animated: true, completion: nil)28                    return Disposables.create()29                }30            }31        }32    }33    34    func present<P, VC>(_ type: VC.Type, dependency: P.Dependency, animated: Bool, withNavigation: Bool = false, presentationStyle: UIModalPresentationStyle = .fullScreen, transitionStyle: UIModalTransitionStyle = .coverVertical) -> Effect<Env, UIViewController> where P: Program, VC: ViewController<P>, P.Environment == Env {35        flatMapT { (vc: UIViewController) -> Effect<Env, UIViewController> in36            Effect<Env, UIViewController> { (env: Env) -> Single<UIViewController> in37                Single<UIViewController>.create { [weak vc] single in38                    guard let vc = vc else { return Disposables.create() }39                    let target: VC = VC()40                    P.bind(with: target, dependency: dependency, environment: env)41                    var targetToPresent: UIViewController42                    if withNavigation {43                        targetToPresent = UINavigationController(rootViewController: target)44                    } else {45                        targetToPresent = target46                    }47                    targetToPresent.modalPresentationStyle = presentationStyle48                    targetToPresent.modalTransitionStyle = transitionStyle49                    vc.present(targetToPresent, animated: animated) {50                        single(.success(targetToPresent))51                    }52                    return Disposables.create()53                }54            }55        }56    }57    func dismiss(animated: Bool) -> Effect<Env, UIViewController> {58        flatMapT { (vc: UIViewController) -> Effect<Env, UIViewController> in59            Effect<Env, UIViewController> { (_: Env) -> Single<UIViewController> in60                Single<UIViewController>.create { [weak vc] single in61                    guard let vc = vc else { return Disposables.create() }62                    vc.dismiss(animated: animated) { single(.success(vc)) }63                    return Disposables.create()64                }65            }66        }67    }68    func push<P, VC>(_ type: VC.Type, dependency: P.Dependency, animated: Bool) -> Effect<Env, UIViewController> where P: Program, VC: ViewController<P>, P.Environment == Env {69        flatMapT { (vc: UIViewController) -> Effect<Env, UIViewController> in70            Effect<Env, UIViewController> { (env: Env) -> Single<UIViewController> in71                Single<UIViewController>.create { [weak vc] single in72                    guard let vc = vc else { return Disposables.create() }73                    let targetToPush: VC = VC()74                    P.bind(with: targetToPush, dependency: dependency, environment: env)75                    vc.navigationController?.pushViewController(targetToPush, animated: animated)76                    single(.success(targetToPush))77                    return Disposables.create()78                }79            }80        }81    }82    func pop(animated: Bool) -> Effect<Env, UIViewController> {83        flatMapT { (vc: UIViewController) -> Effect<Env, UIViewController> in84            Effect<Env, UIViewController> { (_: Env) -> Single<UIViewController> in85                Single<UIViewController>.create { [weak vc] single in86                    guard let vc = vc else { return Disposables.create() }87                    vc.navigationController?.popViewController(animated: animated)88                    single(.success(vc))89                    return Disposables.create()90                }91            }92        }93    }94    func popToRoot(animated: Bool) -> Effect<Env, UIViewController> {95        flatMapT { (vc: UIViewController) -> Effect<Env, UIViewController> in96            Effect<Env, UIViewController> { (_: Env) -> Single<UIViewController> in97                Single<UIViewController>.create { [weak vc] single in98                    guard let vc = vc else { return Disposables.create() }99                    vc.navigationController?.popToRootViewController(animated: animated)100                    single(.success(vc))101                    return Disposables.create()102                }103            }104        }105    }106}...Presentable.swift
Source:Presentable.swift  
...6//  Copyright © 2020 Alexander Yeskin. All rights reserved.7//8import UIKit9protocol Presentable {10    var viewController: UIViewController { get }11    12    func present()13    func present(fromViewController viewController: UIViewController)14    func setRoot(fromViewController viewController: UIViewController)15    func popToRoot()16    func presentModal(fromViewController viewController: UIViewController)17    func show(fromViewController viewController: UIViewController)18    func dissmiss()19    func dissmiss(animated: Bool)20    func dissmissModal(animated: Bool)21    func showModalAnimated(modal: UIViewController)22    func hideModalAnimated(modal: UIViewController)23}24extension Presentable where Self: UIViewController {25    var viewController: UIViewController {26        return self27    }28    func present() {29        AppDelegate.currentWindow.rootViewController = viewController30    }31    func present(fromViewController viewController: UIViewController) {32        viewController.navigationController?.pushViewController(self, animated: true)33    }34    func setRoot(fromViewController viewController: UIViewController) {35        viewController.navigationController?.setViewControllers([self], animated: true)36    }37    38    func popToRoot() {39        self.navigationController?.popToRootViewController(animated: true)40    }41    42    func presentModal(fromViewController viewController: UIViewController) {43        viewController.present(self, animated: true, completion: nil)44    }45    func show(fromViewController viewController: UIViewController) {46        viewController.show(self, sender: viewController)47    }48    func dissmiss() {49        _ = navigationController?.popViewController(animated: true)50    }51    52    func dissmiss(animated: Bool) {53        _ = navigationController?.popViewController(animated: animated)54    }55    func dissmissModal(animated: Bool = true) {56        dismiss(animated: animated, completion: nil)57    }58  59    func showModalAnimated(modal: UIViewController) {60        let transition: CATransition = CATransition()61        transition.duration = 0.162        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)63        transition.type = CATransitionType.fade64        65        if let layer = self.view.window?.layer {66            layer.add(transition, forKey: nil)67        }68        69        modal.modalPresentationStyle = .overFullScreen70        self.present(modal, animated: false, completion: nil)71    }72    73    func hideModalAnimated(modal: UIViewController) {74        let transition: CATransition = CATransition()75        transition.duration = 0.176        transition.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)77        transition.type = CATransitionType.fade78        modal.view.window?.layer.add(transition, forKey: nil)79        self.dismiss(animated: false, completion: nil)80    }81}...UIViewController
Using AI Code Generation
1import Mockingbird2import Mockingbird3import Mockingbird4import Mockingbird5import Mockingbird6import Mockingbird7import Mockingbird8import Mockingbird9import Mockingbird10import Mockingbird11import Mockingbird12import Mockingbird13import Mockingbird14import Mockingbird15import Mockingbird16import Mockingbird17import Mockingbird18import Mockingbird19import Mockingbird20import Mockingbird21import Mockingbird22import MockingbirdUIViewController
Using AI Code Generation
1import UIKit2import Mockingbird3class ViewController: UIViewController {4    override func viewDidLoad() {5        super.viewDidLoad()6    }7}8import UIKit9import Mockingbird10class ViewController: UIViewController {11    override func viewDidLoad() {12        super.viewDidLoad()13    }14}15import UIKit16import Mockingbird17class ViewController: UIViewController {18    override func viewDidLoad() {19        super.viewDidLoad()20    }21}22import UIKit23import Mockingbird24class ViewController: UIViewController {25    override func viewDidLoad() {26        super.viewDidLoad()27    }28}29import UIKit30import Mockingbird31class ViewController: UIViewController {32    override func viewDidLoad() {33        super.viewDidLoad()34    }35}36import UIKit37import Mockingbird38class ViewController: UIViewController {39    override func viewDidLoad() {40        super.viewDidLoad()41    }42}43import UIKit44import Mockingbird45class ViewController: UIViewController {46    override func viewDidLoad() {47        super.viewDidLoad()48    }49}50import UIKit51import Mockingbird52class ViewController: UIViewController {53    override func viewDidLoad() {54        super.viewDidLoad()55    }56}57import UIKit58import Mockingbird59class ViewController: UIViewController {60    override func viewDidLoad() {61        super.viewDidLoad()62    }63}64import UIKitUIViewController
Using AI Code Generation
1import UIKit2import Mockingbird3class ViewController: UIViewController {4    override func viewDidLoad() {5        super.viewDidLoad()6    }7    override func viewWillAppear(_ animated: Bool) {8        super.viewWillAppear(animated)9    }10    override func viewDidAppear(_ animated: Bool) {11        super.viewDidAppear(animated)12    }13}14import UIKit15import Mockingbird16class ViewController: UIViewController {17    override func viewDidLoad() {18        super.viewDidLoad()19    }20    override func viewWillAppear(_ animated: Bool) {21        super.viewWillAppear(animated)22    }23    override func viewDidAppear(_ animated: Bool) {24        super.viewDidAppear(animated)25    }26}27import UIKit28import Mockingbird29class ViewController: UIViewController {30    override func viewDidLoad() {31        super.viewDidLoad()32    }33    override func viewWillAppear(_ animated: Bool) {34        super.viewWillAppear(animated)35    }36    override func viewDidAppear(_ animated: Bool) {37        super.viewDidAppear(animated)38    }39}40import UIKit41import Mockingbird42class ViewController: UIViewController {43    override func viewDidLoad() {44        super.viewDidLoad()45    }46    override func viewWillAppear(_ animated: Bool) {47        super.viewWillAppear(animated)48    }49    override func viewDidAppear(_ animated: Bool) {50        super.viewDidAppear(animated)51    }52}53import UIKit54import Mockingbird55class ViewController: UIViewController {56    override func viewDidLoad() {57        super.viewDidLoad()58    }59    override func viewWillAppear(_ animated: Bool) {60        super.viewWillAppear(animated)61    }62    override func viewDidAppear(_ animated: Bool) {63        super.viewDidAppear(animated)64    }65}66import UIKit67import Mockingbird68class ViewController: UIViewController {69    override func viewDidLoad() {70        super.viewDidLoad()71    }UIViewController
Using AI Code Generation
1import UIKit2import Mockingbird3import XCTest4class ViewController: UIViewController {5    override func viewDidLoad() {6        super.viewDidLoad()7    }8}9class ViewControllerTest: XCTestCase {10    override func setUp() {11        super.setUp()12        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)13        viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController14        viewController.loadView()15        viewController.viewDidLoad()16    }17    func testButton() {18    }19}20import UIKit21import Mockingbird22import XCTest23class ViewController: UIViewController {24    override func viewDidLoad() {25        super.viewDidLoad()26    }27}28class ViewControllerTest: XCTestCase {29    override func setUp() {30        super.setUp()31        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)32        viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController33        viewController.loadView()34        viewController.viewDidLoad()35    }36    func testButton() {37    }38}39import UIKit40import Mockingbird41import XCTest42class ViewController: UIViewController {43    override func viewDidLoad() {44        super.viewDidLoad()45    }46}47class ViewControllerTest: XCTestCase {48    override func setUp() {49        super.setUp()50        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)51        viewController = storyboard.instantiateViewController(withIdentifier: "ViewController") as! ViewController52        viewController.loadView()53        viewController.viewDidLoad()54    }55    func testButton() {56    }57}58import UIKit59import Mockingbird60import XCTest61class ViewController: UIViewController {62    override func viewDidLoad() {63        super.viewDidLoad()64    }65}66class ViewControllerTest: XCTestCase {UIViewController
Using AI Code Generation
1import Mockingbird2import UIKit3class ViewController: UIViewController {4    override func viewDidLoad() {5        super.viewDidLoad()6        label = UILabel()7        button = UIButton()8        button.setTitle("Button", for: .normal)9        button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)10        view.addSubview(label)11        view.addSubview(button)12    }13    override func viewDidLayoutSubviews() {14        super.viewDidLayoutSubviews()15        label.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)16        button.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: view.frame.size.height)17    }18    @objc func buttonTapped() {19    }20}21import Mockingbird22import UIKit23class ViewControllerTests: XCTestCase {24    override func setUp() {25        super.setUp()26        mockViewController = mock(ViewController.self)27        subject = ViewController()28    }29    override func tearDown() {30        super.tearDown()31    }32    func testButtonTapped() {33        given(mockViewController.viewDidLoad()) ~> { }34        given(mockViewController.viewDidLayoutSubviews()) ~> { }35        given(mockViewController.buttonTapped()) ~> { }36        given(mockViewController.label.text) ~> "Button tapped!"37        subject.viewDidLoad()38        subject.viewDidLayoutSubviews()39        subject.buttonTapped()40        XCTAssertEqual(subject.label.text, "Button tapped!")41    }42}43    .package(url: "Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!
