Latest 0.8.3
Homepage https://github.com/DevAndArtist/RxContainer
License MIT
Platforms ios 10.0
Dependencies RxSwift, RxCocoa
Frameworks UIKit
Authors


This Swift module introduces a minimal custom ContainerViewController, which does not contain any unnecessary APIs like UINavigationViewController, nor rely on any protocols such as UIViewControllerTransitioningDelegate etc. for custom transitions.

The end-user is resposible to create custom animators, by conforming to the minimal Animator protocol, which will drive the transitions on the container-view-controller. The ContainerViewController has three different options for pop or push transitions: animated, interactive and immediate.

ContainerViewController:
open class ContainerViewController : UIViewController {
    ///
    open protocol Delegate : AnyObject {
        ///
        func animator(for transition: Transition) -> Animator?
    }

    ///
    public struct Event {
        ///
        public enum Position { case start, end }

        ///
        public let operation: Operation

        ///
        public var position: Position { get }

        ///
        public let containerViewController: ContainerViewController
    }

    ///
    public struct Operation {
        ///
        public enum Kind {
            case push(UIViewController)
            case pop(UIViewController)
            case set([UIViewController])
        }

        ///
        public let kind: Kind

        ///
        public let isAnimated: Bool
    }

    ///
    public enum Option {
        case animated, interactive, immediate
    }

    ///
    open var containerView: UIView { get }

    ///
    open var viewControllers: [UIViewController]

    ///
    open var rootViewController: UIViewController? { get }

    ///
    open var topViewController: UIViewController? { get }

    ///
    open weak var delegate: Delegate?

    /// Initializes and returns a newly created container view controller.
    public init()

    /// Initializes and returns a newly created container view controller.
    ///
    /// This is a convenience method for initializing the receiver and
    /// pushing view controllers onto the view controller stack. Every
    /// view controller stack must have at least one view controller to 
    /// act as the root.
    public convenience init(_ viewControllers: UIViewController...)

    /// Initializes and returns a newly created container view controller.
    ///
    /// This is a convenience method for initializing the receiver and
    /// pushing view controllers onto the view controller stack. Every
    /// view controller stack must have at least one view controller to 
    /// act as the root.
    public convenience init(_ viewControllers: [UIViewController])

    ///
    required public init?(coder aDecoder: NSCoder)

    ///
    open func push(
        _ viewController: UIViewController, 
        option: Option = .animated, 
        with animator: (Transition) -> Animator = RxContainer.animator(for:)
    )

    ///
    @discardableResult
    open func pop(
        option: Option = .animated, 
        with animator: (Transition) -> Animator = RxContainer.animator(for:)
    ) -> UIViewController?

    ///
    @discardableResult
    open func pop(
        to viewController: UIViewController, 
        option: Option = .animated,
        with animator: (Transition) -> Animator = RxContainer.animator(for:)
    ) -> [UIViewController]?

    ///
    @discardableResult
    open func popToRootViewController(
        option: Option = .animated,
        with animator: (Transition) -> Animator = RxContainer.animator(for:)
    ) -> [UIViewController]?

    ///
    open func setViewControllers(
        _ viewControllers: [UIViewController], 
        option: Option = .animated,
        with animator: (Transition) -> Animator = RxContainer.animator(for:)
    )
}

Reactive extension:

extension Reactive where Base : ContainerViewController {
    ///
    public var event: Signal<ContainerViewController.Event>
}
Transition:
public final class Transition {
    ///
    public enum CompletionPosition { case start, end }

    ///
    public struct Context {

        ///
        public enum Key { case from, to }

        ///
        public enum Kind { case push, pop }

        ///
        public let kind: Kind

        ///
        public let containerView: UIView

        ///
        public let isAnimated: Bool

        ///
        public let isInteractive: Bool

        ///
        public func viewController(forKey key: Key) -> UIViewController

        ///
        public func view(forKey key: Key) -> UIView
    }

    ///
    public var additionalAnimation: ((Context) -> Void)? { get }

    ///
    public var additionalCompletion: ((Context) -> Void)? { get }

    ///
    public let context: Context

    ///
    public func animateAlongside(_ animation: ((Context) -> Void)?)

    ///
    public func animateAlongside(
        _ animation: ((Context) -> Void)?, 
        completion: ((Context) -> Void)? = default
    )

    ///
    public func complete(at position: CompletionPosition)
}
Animator:
open protocol Animator : AnyObject {
    ///
    var transition: Transition { get }

    ///
    func animate()

    // Default implementation (no-op)
    func transition(completed: Bool)
}
DefaultAnimator:
public final class DefaultAnimator : Animator {
    ///
    public enum Direction { case left, right, up, down }

    ///
    public enum Style { case overlap, slide }    

    ///
    public enum Order { case normal, reversed }

    ///
    public let transition: Transition

    ///
    public let direction: Direction

    ///
    public let style: Style

    ///
    public let order: Order

    ///
    public init(
        for transition: Transition,
        withDirection direction: Direction,
        style: Style = .overlap,
        order: Order = .normal
    )

    ///
    public func animate()
}

/// Default function for any transition.
public func animator(for transition: Transition) -> Animator

Latest podspec

{
    "name": "RxContainer",
    "version": "0.8.3",
    "summary": "RxContainer provides the missing part between `UINavigationController` and `UIViewController`.",
    "description": "This CocoaPod provides a custom implementation for a `ContainerViewController`. `ContainerViewController`nprovides a very clean API and removes all unnecessary pieces that a `UINavigationController` would have nadded when driving the app flow without the `UINavigationBar`.",
    "homepage": "https://github.com/DevAndArtist/RxContainer",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    },
    "authors": {
        "Adrian Zubarev": "[email protected]"
    },
    "social_media_url": "https://twitter.com/DevAndArtist",
    "platforms": {
        "ios": "10.0"
    },
    "source": {
        "git": "https://github.com/DevAndArtist/RxContainer.git",
        "tag": "0.8.3"
    },
    "source_files": "Sources/*.swift",
    "frameworks": "UIKit",
    "dependencies": {
        "RxSwift": [
            "~> 4.0"
        ],
        "RxCocoa": [
            "~> 4.0"
        ]
    }
}

Pin It on Pinterest

Share This