我在弄清楚如何构造UISplitViewController时遇到了很多麻烦。
我要:
我看到其他应用程序(例如GitHub)也在这样做,但我真的不知道它们是如何管理的。资源很难找到,我所见过的大多数教程只显示了一种或另一种列样式。
我主要是在寻找如何构建这种良好架构的答案,但是任何代码都会受到极大的赞赏!
SceneDelegate
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(frame: windowScene.coordinateSpace.bounds)
window?.windowScene = windowScene
window?.rootViewController = ViewController(style: .tripleColumn)
window?.makeKeyAndVisible()
}
根视图控制器
class ViewController: UISplitViewController {
override func viewDidLoad() {
super.viewDidLoad()
viewControllers = [
SidebarViewController(),
AnimalsViewController(),
AnimalDetailViewController()
]
// Example attempt at removing the secondary view
setViewController(ProfileViewController(), for: .supplementary)
setViewController(nil, for: .secondary)
hide(.secondary)
}
}
理想行为
动物
Profile
干杯!
发布于 2022-06-20 12:05:10
没有“官方”的方法去做,但这是可能的。据我所知,解决这个问题的最好方法之一是在根视图控制器中有两个UISplitViewController
实例,并在需要时在它们之间进行权衡。这是我的方法(大约):
免责声明:在上一次WWDC22 on UIKit实验室期间,该代码与苹果工程师进行了协商。他们证实,非常不幸的是,他们目前没有提供一种方便的办法,而且这种做法可能是最好的办法。反馈被归档,它的ID被传递给工程师,所以希望我们能在iOS 17 :D中得到一个正式的API。
步骤1.初始化UISplitViewController
的
private lazy var doubleColumnSVC: UISplitViewController = {
$0.primaryBackgroundStyle = .sidebar
// setup your SVC here
$0.setViewController(doubleColumnPrimaryNC, for: .primary)
return $0
}(UISplitViewController(style: .doubleColumn))
private lazy var tripleColumnSVC: UISplitViewController = {
$0.primaryBackgroundStyle = .sidebar
// setup your SVC here
$0.setViewController(tripleColumnPrimaryNC, for: .primary)
return $0
}(UISplitViewController(style: .tripleColumn))
步骤2.初始化您的侧栏VC和两个独立的UINavigationController
我发现它是交换边栏VC的最可靠的解决方案。对于单个UINavigationController
实例,存在一个边栏不会随机出现的bug。两个实例解决了这个问题,同时仍然保持单个SidebarVC具有适当的焦点状态,并且已经部署了内容。
// Sidebar is shared and swapped between two split views
private lazy var sideBar = YourSideBarViewController()
private lazy var doubleColumnPrimaryNC = UINavigationController(
rootViewController: UIViewController()
)
private lazy var tripleColumnPrimaryNC = UINavigationController(
rootViewController: UIViewController()
)
步骤3.创建要存储当前显示的SVC的属性
在接下来的步骤中,当两个实例之间切换时,它将派上用场。
private var current: UISplitViewController?
步骤4.在需要时实现两种样式之间的切换
每当您想要导航到与侧栏不同的屏幕时,都应该调用此函数。
private func toggleStyleIfNeeded(_ style: UISplitViewController.Style) {
switch style {
case .doubleColumn:
// skip if the desired column style is already set up
if current === doubleColumnSVC { return }
// reassign current
current = doubleColumnSVC
// here add doubleColumnSVC as child view controller
// here add doubleColumnSVC.view as subview
// swap the sidebar
doubleColumnPrimaryNC.setViewControllers([sideBar], animated: false)
// here remove tripleColumnSVC from parent
// here remove tripleColumnSVC.view from superview
case .tripleColumn:
// skip if the desired column style is already set up
if current === tripleColumnSVC { return }
// reassign current
current = tripleColumnSVC
// here add tripleColumnSVC as child view controller
// here add tripleColumnSVC.view as subview
// swap the sidebar
tripleColumnPrimaryNC.setViewControllers([sideBar], animated: false)
// here remove doubleColumnSVC from parent
// here remove doubleColumnSVC.view from superview
default:
return
}
// If you are using UITabBarController for your compact style, assign it here
current?.setViewController(tabBar, for: .compact)
}
在以“这里”开头的行中,您需要编写自己的代码。我已经简化了代码示例,使其更短。
步骤5.使用动态列享受您的SVC!
现在你基本上准备好了!使用根VC上的这个简单的帮助方法(或任何处理导航和管理SVCs的方法),您将拥有实现所需的所有功能,这是一个具有动态列数的UISplitViewController
!
func setViewController(
_ viewController: UIViewController,
for column: UISplitViewController.Column,
style: UISplitViewController.Style
) {
toggleStyleIfNeeded(style)
current?.setViewController(viewController, for: column)
}
我们在生产中使用这种方法已经有几个月了,而且效果很好。该应用程序支持iOS、iPadOS和Mac催化剂。有一些东西,比如定制状态栏样式和获得一致的侧边栏按钮,要完美地工作有点棘手,但是有了一些调整和UISplitViewControllerDelegate
的帮助,一切都是可能的。
祝好运!
如果有人曾经走过这条路,并且能够分享建议,请这样做!我想了解更多关于如何提高用户和开发人员的动态拆分视图体验的知识。
发布于 2022-06-19 04:06:54
要从3列切换到2列,您必须使用两列(UISplitViewController(style: .doubleColumn
)重新初始化UISplitViewController(style: .doubleColumn
并将其重新分配到window.rootViewController
。
在重新初始化UISplitViewController
时,可以分配现有的视图控制器对象来维护当前状态,也可以初始化新的状态。如果您分配了现有的视图控制器对象,那么在第一次创建这些对象之后,将它们存储在变量中可能是很方便的。
https://stackoverflow.com/questions/68336349
复制