Skip to content

Commit c95f58d

Browse files
committed
commit: update navigator
1 parent a01ad73 commit c95f58d

File tree

2 files changed

+88
-18
lines changed

2 files changed

+88
-18
lines changed

Example/ModuleRouteExample.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Lines changed: 0 additions & 7 deletions
This file was deleted.

Sources/ModuleRoute/MRNavigator.swift

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public class MRNavigator {
5959
}
6060

6161
public func navigate(to route: MRRoute,
62-
from viewController: UIViewController,
62+
from viewController: UIViewController? = nil,
6363
navigationType: NavigationType = .push,
6464
animated: Bool = true,
6565
completion: (() -> Void)? = nil) {
@@ -82,8 +82,8 @@ public class MRNavigator {
8282
return false
8383
}
8484

85-
if let rootVC = UIApplication.shared.windows.first(where: { $0.isKeyWindow })?.rootViewController {
86-
navigate(to: route, from: rootVC)
85+
if let topvc = topViewController() {
86+
navigate(to: route, from: topvc)
8787
return true
8888
}
8989
return false
@@ -121,7 +121,7 @@ public class MRNavigator {
121121
}
122122

123123
private func handleResult(_ result: RouteResult,
124-
from viewController: UIViewController,
124+
from viewController: UIViewController?,
125125
navigationType: NavigationType,
126126
animated: Bool,
127127
completion: (() -> Void)?) {
@@ -143,21 +143,31 @@ public class MRNavigator {
143143
}
144144

145145
private func perform(navigation type: NavigationType,
146-
from: UIViewController,
146+
from: UIViewController?,
147147
to: UIViewController,
148148
animated: Bool,
149149
completion: (() -> Void)?) {
150+
var temp = (from != nil) ? from : topViewController()
151+
guard let base = temp else {
152+
completion?()
153+
return
154+
}
150155
switch type {
151156
case .push:
152-
from.navigationController?.pushViewController(to, animated: animated)
153-
completion?()
157+
if let navigationController = base.navigationController {
158+
navigationController.pushViewController(to, animated: animated)
159+
completion?()
160+
} else {
161+
let nav = UINavigationController(rootViewController: to)
162+
base.present(nav, animated: animated, completion: completion)
163+
}
154164
case .present:
155-
from.present(to, animated: animated, completion: completion)
165+
base.present(to, animated: animated, completion: completion)
156166
case .modal:
157167
to.modalPresentationStyle = .fullScreen
158-
from.present(to, animated: animated, completion: completion)
168+
base.present(to, animated: animated, completion: completion)
159169
case .replace:
160-
guard let navigationController = from.navigationController else {
170+
guard let navigationController = base.navigationController else {
161171
completion?()
162172
return
163173
}
@@ -167,7 +177,7 @@ public class MRNavigator {
167177
navigationController.setViewControllers(viewControllers, animated: animated)
168178
completion?()
169179
case .custom(let handler):
170-
handler(from, to)
180+
handler(base, to)
171181
completion?()
172182
}
173183
}
@@ -185,3 +195,70 @@ public class MRNavigator {
185195
metadata: ["params": route.params, "result": String(describing: result)])
186196
}
187197
}
198+
199+
200+
public extension MRNavigator {
201+
202+
/// Get the top most view controller from the base view controller; default param is UIWindow's rootViewController
203+
func topViewController(_ from: UIViewController? = nil) -> UIViewController? {
204+
var base = (from != nil) ? from : compatibleKeyWindow?.rootViewController
205+
if let nav = base as? UINavigationController {
206+
return topViewController(nav.visibleViewController)
207+
}
208+
if let tab = base as? UITabBarController {
209+
if let selected = tab.selectedViewController {
210+
return topViewController(selected)
211+
}
212+
}
213+
if let presented = base?.presentedViewController {
214+
return topViewController(presented)
215+
}
216+
return base
217+
}
218+
219+
var compatibleKeyWindow: UIWindow? {
220+
if #available(iOS 13, *) {
221+
return UIApplication.shared.connectedScenes
222+
.compactMap { $0 as? UIWindowScene }
223+
.flatMap { $0.windows }
224+
.first { $0.isKeyWindow }
225+
} else {
226+
return UIApplication.shared.keyWindow
227+
}
228+
}
229+
/// 重置应用到根视图控制器
230+
func resetToRootViewController(_ animated: Bool = false) {
231+
guard let window = compatibleKeyWindow,
232+
let rootViewController = window.rootViewController else {
233+
return
234+
}
235+
236+
// 1. 先处理当前显示的模态视图
237+
if let presentedVC = rootViewController.presentedViewController {
238+
presentedVC.dismiss(animated: false) {
239+
self.resetToRootHelper(rootViewController, animated: animated)
240+
}
241+
} else {
242+
resetToRootHelper(rootViewController, animated: animated)
243+
}
244+
}
245+
246+
private func resetToRootHelper(_ rootViewController: UIViewController, animated: Bool) {
247+
// 2. 处理 UINavigationController
248+
if let navigationController = rootViewController as? UINavigationController {
249+
navigationController.popToRootViewController(animated: animated)
250+
}
251+
252+
// 3. 处理 UITabBarController
253+
if let tabBarController = rootViewController as? UITabBarController {
254+
// 重置所有 tab 的导航栈
255+
tabBarController.viewControllers?.forEach { viewController in
256+
if let navigationController = viewController as? UINavigationController {
257+
navigationController.popToRootViewController(animated: animated)
258+
}
259+
}
260+
// 切换到第一个 tab
261+
tabBarController.selectedIndex = 0
262+
}
263+
}
264+
}

0 commit comments

Comments
 (0)