用于管理应用程序中导航的充分且超级方便的解决方案
🚂 过渡
Transition
for Swift 是管理应用程序内导航的足够且超级方便的解决方案。您不需要“包装”控制器,或使用“基”类或协调器等。
使用该库归结为创建 and 类并从 .您甚至不必使用新协议扩展控制器本身。Router
Route
UIViewController
以下是它的工作原理:
🌱 Getting started
// 1️⃣ For UIViewController you create a router that will
// call the screen with the correct way to open
class HomeRouter: Router<HomeViewController> {}
// 2️⃣ Router should be in your UIViewController and be
// initialized at the time of the call
class HomeViewController: UIViewController {
var router: ProfileRouter
init(router: ProfileRouter) {
self.router = router
}
}
// 3️⃣ At the same time, each module must have its own route,
// which will describe the methods in which the new screen will be initialized
protocol ProfileRoute {
func presentProfile()
func pushProfile()
}
extension ProfileRoute where Self: RouterProtocol {
// This is how the function to show the Profile in the modal window would look like
func presentProfile() {
// Use one of the preset opening schemes or implement your own.
let transition = ModalTransition()
// Transition needs to be passed to the router, which is stored in your controller
// It is convenient to do this in a class that assembles a module,
// such as Assembly in VIPER
let module = ProfileModule(transition: transition)
// The Transition library method is called into which the opened UIViewController
// will be passed and opening method
open(module.view, transition: transition)
}
// This is how the function to push Profile in current Navigation stack
func pushProfile() {
let transition = PushTransition()
let module = ProfileModule(transition: transition)
open(module.view, transition: transition)
}
}
// 4️⃣ And... that's all - you can call the router methods in your `UIViewController`
// in a convenient way for you, like this:
profileButton.addAction(
UIAction(handler: { [weak self] _ in
self?.router.presentProfile()
}),
for: .touchUpInside
)
🌠 Demo
For a better understanding of how to work with , please check out the demo project.Transition
🦖 For more
-
The module’s native “push” and “present” are already defined in and , just pass an instance of them to the method.
PushTransition
ModalTransition
open(_ : UIViewController, : Transition)
-
In addition, there is which replaces the current controller with a new one using the method
EmbedTransition
didMove(toParent _: UIViewController?)
-
For a modal view, you can pass configuration in the BottomSheetProps object. It is supported to change all (or at least the most important) settings that will ensure the correct behavior of the screen.
// Each property replicates native settings in UIKit, you shouldn't have
// not understanding how it works. Just in case, for the BottomSheetProps properties,
// their documentation is duplicated
let transition = ModalTransition(
isAnimated: true,
isNeedToEmbedInNavigationController: false,
modalPresentationStyle: .pageSheet,
bottomSheetProps: BottomSheetProps(
doNotCloseOnDrag: false,
detents: [
.large(),
.medium()
],
selectedDetentIdentifier: .medium,
prefersScrollingExpandsWhenScrolledToEdge: true,
largestUndimmedDetentIdentifier: .medium,
preferredCornerRadius: 32,
prefersGrabberVisible: true
)
)
- If your project already uses , or any other screen opening animator, you can use it in conjunction with . Just implement your own version of the Transition protocol. Like that:
PanModal
FloatingPanel
Transition
import FloatingPanel
import UIKit
final class ModalFloatingPanelTransition: NSObject {
weak var viewController: UIViewController?
weak var floatingPanel: FloatingPanelController?
}
// MARK: - Transition
extension ModalFloatingPanelTransition: Transition {
func open(_ viewController: UIViewController) {
guard let selfController = self.viewController else { return }
guard
let delegate = viewController as? FloatingPanelControllerDelegate
else {
assertionFailure("`\(viewController.self)` must conform `FloatingPanelControllerDelegate`")
return
}
let fpc = FloatingPanelController()
floatingPanel = fpc
delegate.floatingPanel = fpc
fpc.set(contentViewController: viewController)
delegate.floatingPanelDidCreate(fpc)
// Other FloatingPanelController settings if needed
let controller = selfController.presentedViewController ?? selfController
controller.present(fpc, animated: animated) { [weak delegate, weak fpc] in
guard
let delegate = delegate,
let fpc = fpc
else {
return
}
delegate.floatingPanelDidPresent(fpc)
}
}
func close(_ viewController: UIViewController) {
close(viewController, completion: {})
}
func close(_: UIViewController, completion: @escaping () -> Void) {
floatingPanel?.dismiss(animated: animated) { [weak self] in
self?.floatingPanel?.set(contentViewController: nil)
completion()
}
}
}