容器

CI Status GitHub tag (latest SemVer) License

ContainerViewController 旨在成为一种简单而灵活的方法,用于嵌入多个子 UIViewController 对象并在它们之间进行过渡。 它被设计用来填补当你需要一个没有导航栏的 UINavigationController,或者一个没有标签栏的 UITabBarController 时的空白。 在容器的子视图之间进行过渡的唯一内置方法是通过其 transition(to:) API。

为了快速入门,最简单的方法是从代码创建 ContainerViewController,并手动将其添加为父 UIViewController 的子视图。 这很容易在该视图控制器的 viewDidLoad 函数中完成

private lazy var containerViewController: ContainerViewController = ContainerViewController(children: [.init(identifier: .a, viewController: controllerA),
                                                                                                       .init(identifier: .b, viewController: controllerB)], delegate: self)

containerViewController.willMove(toParent: self)

addChild(containerViewController)
containerView.addSubview(containerViewController.view)
containerViewController.view.frame = containerView.bounds

containerViewController.didMove(toParent: self)

你会注意到在这个例子中我们能够使用静态类型标识符,.a.b。 这是因为在 ContainerViewController.Child.Identifier 上声明了一个扩展,很简单

extension ContainerViewController.Child.Identifier {
    static let a = ContainerViewController.Child.Identifier(rawValue: "A")
    static let b = ContainerViewController.Child.Identifier(rawValue: "B")
}

尽管这是推荐的做法,但 ContainerViewController.Child.Identifier 遵循 ExpressibleByStringLiteralRawRepresentable,因此这些标识符可以在运行时从任何 String 初始化。

一旦你正确初始化并显示了 ContainerViewController,它将(默认情况下)自动过渡到它的第一个 Child。 此行为由 shouldAutomaticallyTransitionOnLoad 控制,当设置为 true 时,容器将在其视图加载时选择其 Child 对象中的第一个。 如果此值设置为 false,或者 ContainerViewController 在加载时没有 Child 对象,它将等待进一步的指令,然后再嵌入和显示 Child

为了开始显示子视图控制器,有几个选项

// If `child` is not already part of `ContainerViewController`, it will be added before it is displayed
let child = ContainerViewController.Child(identifier: .new, viewController: someViewController)
containerViewController.transition(to: child) { finished in
    print("finished transitioning: \(finished)")
}

// If you know the identifier of an existing `Child` that is part of the container, you can alternatively request it:
containerViewController.transitionToChild(for: .new) { finished in
    print("finished transitioning: \(finished)")
}

容器还具有几个委托回调,可以帮助自定义其行为。 其中,有一个函数返回一个 UIViewControllerAnimatedTransitioning 对象,其使用方式与模态、导航和标签过渡动画中使用的对象相同。

func containerViewController(_ container: ContainerViewController, animationControllerForTransitionFrom source: Child, to destination: Child) -> UIViewControllerAnimatedTransitioning? {
    if useCustomAnimator, let sourceIndex = container.index(ofChild: source.viewController), let destinationIndex = container.index(ofChild: destination.viewController) {
        return WipeTransitionAnimator(withStartIndex: sourceIndex, endIndex: destinationIndex)
    }

    return nil
}

灵感

Container 是 ContainerViewController 的演变,该视图控制器曾是 UtiliKit 的一部分。 在大多数情况下,两者在源代码上是兼容的,但如果你要从 UtiliKit 升级到 Container,请查看我们的 迁移指南

示例

要运行示例项目,请克隆此仓库并打开 iOS Example/iOS Example.xcworkspace

要求

需要 iOS 10.0、tvOS 10.0

安装

使用 Swift Package Manager 将其添加到您的项目中。 在 Xcode 中,只需:File > Swift Packages > Add Package Dependency... 即可完成。 以下显示了传统项目的替代安装选项。

CocoaPods

如果您已在使用 CocoaPods,只需将 'Container' 添加到您的 Podfile,然后运行 pod install

Carthage

如果您已在使用 Carthage,只需添加到您的 Cartfile

github "BottleRocketStudios/Container" ~> 0.1

然后运行 carthage update 以构建框架,并将构建的 Container.framework 拖到您的 Xcode 项目中。

作者

Bottle Rocket Studios

许可证

Container 在 Apache 2.0 许可证下可用。 有关更多信息,请参见 LICENSE 文件

贡献

请参阅 CONTRIBUTING 文档。 谢谢您,贡献者