Latest 4.0.2
Homepage https://github.com/MLSDev/AppRouter
License MIT
Platforms ios 8.0, requires ARC
Authors

AppRouter Logo
Build Status  
codecov.io
CocoaPod platform  
CocoaPod version  
Carthage compatible
[Packagist]()

Extremely easy way to handle controller creation / presentation / navigation and reduce coherence in project in general.

Requirements

  • iOS 8.0+
  • Xcode 9+
  • Swift 3.2

Installation

CocoaPods

pod 'AppRouter'

RxSwift extension for AppRouter with lifeCircle observables:

pod 'AppRouter/RxSwift'

Carthages

github "MLSDev/AppRouter"

Examples

Presentations

Imagine that you want to present some controller and for this you need other controller to present on. Usual way forces us to pass controller through weak properties or to use delegation mechanic. We can avoid this situation and just call:

AppRouter.topViewController?.present(newOne, animated: true, completion: nil)

or even

newOne.presenter().present()

Easy accessors

// provides access to keyWindow (also creates one if current is nil)
AppRouter.window

// root controller in current window stack
AppRouter.rootViewController

// topmost controller
AppRouter.topViewController

// returns instance of passed type if its present in tabBar (even if it's embedded in navigationController)
tabBarController.getControllerInstance<T: UIViewController>(_:) -> T?

// returns instance of passed type if its present in navigationController
navigationController.getControllerInstance<T: UIViewController>(_:) -> T?

// returns true if current controller modally presented
viewController.isModal

Easy Construction, Configuration, Presentation

Of course it’s always better to extract controller creation, configuration and presentation logic out of other controllers and views into FlowControllers or just simple extension methods (if you want this new controller work results – give them completion block or try using reactive ways). This will significantly reduce coherence and allow you to modify only one place in whole app to change logic behind feature :

extension AppRouter {
  static func openGridPictureGalleryControllerWith(pictures: PicturesRepresentation) {
    GridPictureGalleryController.presenter().fromStoryboard("GridPictureGallery").embedInNavigation().configure{
      $0.picturesRepresentation = pictures
    }.present()
  }
  static func openChangePasswordController() {
    ChangePasswordViewController.presenter().push()
  }
}

Note: framework by default uses name of your UIViewController subclass (String(describing: controllerType)) as storyboard identifier and initial controller (or rootViewController on initial UINavigationController)

Completion handlers

In addition to presentation / dismissal completion blocks provided by UiKit, AppRouter provides you completion blocks for pushing/popping controllers onto navigation stack:

pushViewController(_, animated:, completion:)
popViewController(animated animated:, completion:)
popToViewController(_:, animated:, completion:)
popToRootViewController(animated animated:, completion:)
popToViewController<T: UIViewController>(_:, animated:, completion:)

Closing controller

Another possible scenario: feature controller that can be pushed or presented in different parts of application. Simplest way to make such controller gone (close button or etc) is to use close method. Just:

@IBAction func closeTapped(sender: UIButton!) {
  self.close()
}

And thats it. Method will try to detect the proper way to make controller gone.

RxSwift extensions

If you want some easy way to deal with controller lifecycle outside – try to use AppRouter/RxSwift subspec. It provides a bunch of Type and Instance observables around lifecycle methods (it uses swizzling underneath from the moment you subscribe) :

instance.rx.onViewDidLoad() -> Observable<Void>
instance.rx.onViewWillAppear() -> Observable<Bool>
instance.rx.onViewDidAppear() -> Observable<Bool>
instance.rx.onViewWillDisappear() -> Observable<Bool>
instance.rx.onViewDidDisappear() -> Observable<Bool>

Type.rx.onViewDidLoad() -> Observable<Type>
Type.rx.onViewWillAppear() -> Observable<(controller: Type, animated: Bool)>
Type.rx.onViewDidAppear() -> Observable<(controller: Type, animated: Bool)>
Type.rx.onViewWillDisappear() -> Observable<(controller: Type, animated: Bool)>
Type.rx.onViewDidDisappear() -> Observable<(controller: Type, animated: Bool)>

Latest podspec

{
    "name": "AppRouter",
    "version": "4.0.2",
    "summary": "UIViewController creation, navigation, utility methods for easy routing",
    "homepage": "https://github.com/MLSDev/AppRouter",
    "license": "MIT",
    "authors": {
        "Artem Antihevich": "[email protected]"
    },
    "social_media_url": "https://twitter.com/sinarionn",
    "platforms": {
        "ios": "8.0"
    },
    "source": {
        "git": "https://github.com/MLSDev/AppRouter.git",
        "tag": "4.0.2"
    },
    "requires_arc": true,
    "default_subspecs": "Core",
    "pushed_with_swift_version": "3.2",
    "subspecs": [
        {
            "name": "Core",
            "ios": {
                "frameworks": [
                    "UIKit",
                    "Foundation"
                ]
            },
            "source_files": "Sources/Core/*.swift"
        },
        {
            "name": "RxSwift",
            "dependencies": {
                "AppRouter/Core": [],
                "RxSwift": [
                    "~> 3.0"
                ]
            },
            "source_files": "Sources/RxSwift/*.swift"
        }
    ]
}

Pin It on Pinterest

Share This