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) -> 在二级导航中显示
- TabBarController ->
- NavigationController ->
- TabBarController ->
- 许多...
- TableViewControllers ->
- DetailController -> 它可以无限深入。
- FilteringController
- Create/EditController
- CollectionControllers ->
- FilteringController
- Create/EditController
- SomeCustomControllers
- TabBarController ->
- NavigationController ->
且这种结构可以无限深入。因此,在某个时候,我决定创建自己的导航。目前,它与我们的控制器结构工作得更好。
安装
您可以通过CocoaPods安装它,或者将TidySplits的源代码复制粘贴到您的项目中。
通过CocoaPods安装,只需在您的pods文件中添加以下行
pod 'TidySplits'
然后从控制台运行
pod install
运行示例项目
下载整个项目后,您可以通过运行目标'target 'TidySplitsExample'来检查它的工作方式。该项目包含TidySplits应该如何配置的简单示例。非常简单!
示例项目包含两个重要的文件:ExampleViewController.swift和MainSplitViewController.Swift,第一个是为了展示一些导航功能如何工作而创建的。第二个是所有内容开始的起点 :).
如何开始使用TidySplits
您的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请求。
作者
- 托马什·卡明斯基 - 创建者 - TomKaminski
请参阅参与此项目的贡献者列表。
许可协议
此项目采用MIT许可协议 - 详细信息请参阅LICENSE文件。