TidySplits 2.2.0

TidySplits 2.2.0

Tomasz Kaminski 维护。



  • 作者:
  • Tomasz Kaminski

TidySplits

TidySplits 是另一种设置 Split 布局的途径。由于 Apple 原始 SplitViewController 配置选项较少,因此创建了它。TidySplits 使用 Swift 4.2 构建,并支持 iOS 9 以上。

为何创建此插件?

我个人在我的商用项目中觉得 Apple 的 SplitViewController 过于复杂。控制 Compact 和 Regular 接口之间的转换很困难。项目视图控制器结构如下

  • SplitViewController ->
    • NavigationController ->
      • TabBarController ->
        • 许多...
        • TableViewControllers ->
        • FilteringController
        • Create/EditController (在 Regular 设备上的 DetailContext) -> 在二级导航中显示
        • TabBarDetailController (在 Regular 设备上的 DetailContext) -> 在二级导航中显示
    • NavigationController ->
      • TabBarController ->
        • 许多...
        • TableViewControllers ->
          • DetailController -> 它可以无限深入。
          • FilteringController
          • Create/EditController
        • CollectionControllers ->
          • FilteringController
          • Create/EditController
        • SomeCustomControllers

且这种结构可以无限深入。因此,在某个时候,我决定创建自己的导航。目前,它与我们的控制器结构工作得更好。

安装

您可以通过CocoaPods安装它,或者将TidySplits的源代码复制粘贴到您的项目中。

通过CocoaPods安装,只需在您的pods文件中添加以下行

pod 'TidySplits' 

然后从控制台运行

pod install

运行示例项目

下载整个项目后,您可以通过运行目标'target 'TidySplitsExample'来检查它的工作方式。该项目包含TidySplits应该如何配置的简单示例。非常简单!

示例项目包含两个重要的文件:ExampleViewController.swift和MainSplitViewController.Swift,第一个是为了展示一些导航功能如何工作而创建的。第二个是所有内容开始的起点 :).

如何开始使用TidySplits

您的SplitViewController是一个基础。

首先,就像在示例项目中一样,您必须创建一个继承自的SplitViewController。

示例代码中的控制器如下所示

class ExampleSplitViewController: TidySplitsUISplitViewController, TidySplitsSplitViewDelegate {
  var shouldOmitDetailChildsForCompactMode: Bool {
    return false
  }
  
  override func viewDidLoad() {
    self.delegate = self
    super.viewDidLoad()
  }
  
  func getDetailsPlaceholder() -> TidySplitsChildControllerProtocol {
    let ctrl = ExampleViewController(.Detail)
    ctrl.view.backgroundColor = .green
    return ctrl
  }
  
  func getInitialPrimaryControllers() -> [TidySplitsChildControllerProtocol] {
    let ctrl = ExampleViewController(.Primary)
    ctrl.view.backgroundColor = .blue
    return [ctrl]
  }
  
  func getInitialDetailControllers() -> [TidySplitsChildControllerProtocol] {
    let ctrl = ExampleViewController(.Detail)
    ctrl.view.backgroundColor = .red
    return [ctrl]
  }
}

viewDidLoad方法中,您必须指定代理。为了简化,我们的控制器就是它的自己的代理 :). 代理协议声明了所需方法和属性,以正确配置。

public protocol TidySplitsSplitViewDelegate: class {
  
  /**
   Computed get only property which decides if we should omit details stack when transitioning from **regular** to **compact** layout.
   */
  var shouldOmitDetailChildsForCompactMode: Bool { get }

  /**
  Delegate method to define which controller (or controllers) starts primary stack.
  */
  func getInitialPrimaryControllers() -> [TidySplitsChildControllerProtocol]
  
  /**
   Delegate method to define which controller (or controllers) starts detail stack.
   */
  func getInitialDetailControllers() -> [TidySplitsChildControllerProtocol]
  
  /**
   Delegate method to define which controller should be shown if detail stack is empty and we transition to **regular** "splitted" layout.
   */
  func getDetailsPlaceholder() -> TidySplitsChildControllerProtocol
}

每个子控制器都应该遵守 TidySplitsChildControllerProtocol

此协议是该库中所有功能的核心。

public protocol TidySplitsChildControllerProtocol: class {
  var prefferedDisplayType: TidySplitsChildPreferedDisplayType { get set }
  
  var tidySplitController: TidySplitsUISplitViewController? { get }
  var tidyNavigationController: TidySplitsUINavigationController? { get }
  
  func postPopSelfNotification()
  func popSelf() -> UIViewController?
}

最重要的事情是 preferedDisplayType 属性。它决定了特定控制器应该被推送到哪里(主栈或详情栈)。

我已经创建并定义了一些基本控制器,您可以将它们用作自定义控制器的基础

  • TidySplitsUIViewController - UIViewController 的子类
  • TidySplitsUITableViewController - UITableViewController 的子类
  • TidySplitsUITabBarViewController - UITabBarController 的子类

好的,我已经配置了自己的分割控制器,并创建了一些符合 TidySplitsChildControllerProtocol 的子对象,接下来怎么办?

现在,您最终可以使应用程序 导航!有多种方式可以执行导航。

从分割控制器

  open func showDetail(_ controller: TidySplitsChildControllerProtocol, _ animated: Bool = true, _ completion: ((TidySplitsChildControllerProtocol) -> Void)? = nil)

  open func push(_ controller: TidySplitsChildControllerProtocol, _ animated: Bool = true, _ completion: ((TidySplitsChildControllerProtocol) -> Void)? = nil)
  
  open func tryPush(_ controller : UIViewController, _ animated: Bool = true, _ completion: ((TidySplitsChildControllerProtocol) -> Void)? = nil) -> Bool
  
  @discardableResult open func pop(from type: TidySplitsChildPreferedDisplayType, _ animated: Bool = true, _ completion: ((UIViewController?) -> Void)? = nil) -> UIViewController?
  • showDetail 方法用指定的控制器替换当前的详情栈。
  • push 方法定义为将新的控制器推送到主栈或详情栈,这取决于控制器的 preferedDisplayType 属性。
  • tryPush 方法尝试(如果它符合我们的 ChildProtocol)将新的控制器推送到主栈或详情栈,这取决于控制器的 preferedDisplayType 属性。
  • pop 方法从指定类型中弹出当前显示的控制器。

从导航控制器

  open func pushToMe(_ controller: TidySplitsChildControllerProtocol, _ animated: Bool = true, _ completion: ((TidySplitsChildControllerProtocol) -> Void)? = nil)
  
  open func tryPushToMe(_ controller: UIViewController, _ animated: Bool = true, _ completion: ((TidySplitsChildControllerProtocol) -> Void)? = nil) -> Bool
  
  open func popFromMe(animated: Bool = true, _ completion: ((UIViewController?) -> Void)? = nil)
  • pushToMe 方法将控制器推送到当前导航,并将其首选类型更改为导航控制器的类型 - 在使用此方法时请考虑一下!
  • tryPushToMe 方法尝试将控制器推送到当前导航(如果子类符合 ChildProtocol)并将其首选类型更改为导航控制器的类型 - 在使用此方法时请考虑一下!
  • popFromMe 方法从当前导航控制器中弹出显示的控制器

从子控制器

子控制器协议定义了以下属性

  var tidySplitController: TidySplitsUISplitViewController? { get }
  var tidyNavigationController: TidySplitsUINavigationController? { get }

这使得您可以在子代码中使用 Split/Navigation 控制器的功能。

此外,子控制器还可以 popSelf() :)

我发现了一个错误。

那不错,我大约在8小时内匆忙写的。我100%确信您会发现一些东西。创建一个问题,我们可以一起让它变得更好:)

待办事项

  • 瞬移功能
  • 提供更好的配置选项
  • 记录代码

贡献

只需提交一个pull请求。

作者

请参阅参与此项目的贡献者列表

许可协议

此项目采用MIT许可协议 - 详细信息请参阅LICENSE文件。