如何在 Swift 中弹出特定的视图控制器
How can I pop specific View Controller in Swift
我使用了下面的 Objective-C
代码来弹出一个特定的 ViewController
。
for (UIViewController *controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[AnOldViewController class]]) {
//Do not forget to import AnOldViewController.h
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}
我如何在 Swift 中做到这一点?
试试下面的代码:
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: ViewController.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
为Swift3+
let viewControllers: [UIViewController] = self.navigationController!.viewControllers
for aViewController in viewControllers {
if aViewController is YourViewController {
self.navigationController!.popToViewController(aViewController, animated: true)
}
}
我更喜欢通用的方式。
我有 UINavigationController 的这个扩展:
extension UINavigationController {
func backToViewController(vc: Any) {
// iterate to find the type of vc
for element in viewControllers as Array {
if "\(element.dynamicType).Type" == "\(vc.dynamicType)" {
self.popToViewController(element, animated: true)
break
}
}
}
}
假设我在导航堆栈中实例化了一个 FOHomeVC class(它是一个 UIViewController)。
所以我会在我的代码中这样做:
self.navigationController?.backToViewController(FOHomeVC.self)
请为 Swift 3.0 使用以下代码:
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
for aViewController:UIViewController in viewControllers {
if aViewController.isKind(of: YourViewController.self) {
_ = self.navigationController?.popToViewController(aViewController, animated: true)
}
}
Swift 4.0
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: DashboardVC.self) {
_ = self.navigationController!.popToViewController(controller, animated: true)
break
}
}
这很完美。
我在 UINavigationController
中添加了一个扩展,它可以帮助您找到该控制器是否存在于导航堆栈中。如果是,那么它将被弹出到该控制器,否则您将传递新的控制器以使用 pushController
参数进行推送。
extension UINavigationController {
func containsViewController(ofKind kind: AnyClass) -> Bool {
return self.viewControllers.contains(where: { [=10=].isKind(of: kind) })
}
func popPushToVC(ofKind kind: AnyClass, pushController: UIViewController) {
if containsViewController(ofKind: kind) {
for controller in self.viewControllers {
if controller.isKind(of: kind) {
popToViewController(controller, animated: true)
break
}
}
} else {
pushViewController(pushController, animated: true)
}
}
}
最近 swift
@IBAction func popToConversationsVC(_ sender: UIButton) {
if (self.navigationController != nil) {
for vc in self.navigationController!.viewControllers {
if vc is ConversationsVC {
self.navigationController?.popToViewController(vc, animated: false)
}
}
}
}
从导航堆栈中找到您的视图控制器,如果存在则弹出到该视图控制器
for vc in self.navigationController!.viewControllers {
if let myViewCont = vc as? VCName
{
self.navigationController?.popToViewController(myViewCont, animated: true)
}
}
Swift 4 / Swift 5
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: HomeViewController.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
我需要使用它,因为在某些情况下应用会崩溃:
if let navVC = self.navigationController {
let views = navVC.viewControllers as Array
for controller in views {
if controller.isKind(of: YourVC.self) {
navVC.popToViewController(controller, animated: true)
return
}
}
}
Swift 5
弹出特定 class 的最新实例,例如 SomeViewController
:
navigationController?.popToViewController(ofClass: SomeViewController.self)
但您需要添加 UINavigationController
扩展名:
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.last(where: { [=11=].isKind(of: ofClass) }) {
popToViewController(vc, animated: animated)
}
}
}
extension UINavigationController {
func popBack(to vc: AnyClass, animated: Bool = true) {
guard let elementFound = (viewControllers.filter { [=10=].isKind(of: vc) }).first else {
fatalError("cannot pop back to \(vc) as it is not in the view hierarchy")
}
self.popToViewController(elementFound, animated: animated)
}
}
没有强制展开的简单且最佳的解决方案是
if let vc = navigationController.viewControllers.filter({[=10=] is YourViewController}).first as? YourViewController {
self.navigationController.popToViewController(vc, animated: true)
}
swift5
let controllers : Array = self.navigationController!.viewControllers
self.navigationController!.popToViewController(controllers[1], animated: true)
我更喜欢 "real generic" 和更实用的方法。
所以我想出了以下 UINavigationController
扩展函数。您还可以将第一个函数用于其他用途,您只需要访问导航堆栈中的特定 VC。
扩展
extension UINavigationController {
func getViewController<T: UIViewController>(of type: T.Type) -> UIViewController? {
return self.viewControllers.first(where: { [=10=] is T })
}
func popToViewController<T: UIViewController>(of type: T.Type, animated: Bool) {
guard let viewController = self.getViewController(of: type) else { return }
self.popToViewController(viewController, animated: animated)
}
}
用法
self.navigationController?.popToViewController(of: YourViewController.self, animated: true)
这应该至少在 Swift 4 和 5 中有效。
Swift 5 @PabloR 的答案在这里:
extension UINavigationController {
func backToViewController(vc: Any) {
// iterate to find the type of vc
for element in viewControllers as Array {
if "\(type(of: element)).Type" == "\(type(of: vc))" {
self.popToViewController(element, animated: true)
break
}
}
}
}
用法:
self.navigationController?.backToViewController(vc: TaskListViewController.self)
对于 Swift 4.0 及更高版本使用过滤器
guard let VC = self.navigationController?.viewControllers.filter({[=10=].isKind(of: YourViewController.self)}).first else {return}
self.navigationController?.popToViewController(VC, animated: true)
这个解决方案对我有用:)
extension UINavigationController {
func backToViewController(_ viewController: AnyClass, animated: Bool) {
guard let viewController = self.viewControllers.first(where: {[=10=].isKind(of: viewController)}) else { return }
self.popToViewController(viewController, animated: animated)
}
}
我改编自以上所有答案。它看起来像 Yakup Ad 答案,因为它的路很短。
- 我通过对参数使用泛型来强制类型,确保您必须只将 UIViewController 传递给此函数。
- 我使用 .first 搜索已经在堆栈中的 viewController。这让我只有一个 VC 然后停止循环。
- 如果你需要定制一些东西,我也会return传递VC。
让我们尽情享受吧。
extension UINavigationController {
func popToViewController<T: UIViewController>(_ viewController: T.Type, animated: Bool) -> T? {
guard let viewController = self.viewControllers.first(where: {[=10=] is T}) else { return nil }
self.popToViewController(viewController, animated: animated)
return viewController as? T
}
}
用法
let poppedVC = self.navigationController?.popToViewController(HomeViewController.self, animated: true)
我使用了下面的 Objective-C
代码来弹出一个特定的 ViewController
。
for (UIViewController *controller in self.navigationController.viewControllers) {
if ([controller isKindOfClass:[AnOldViewController class]]) {
//Do not forget to import AnOldViewController.h
[self.navigationController popToViewController:controller
animated:YES];
break;
}
}
我如何在 Swift 中做到这一点?
试试下面的代码:
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: ViewController.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
为Swift3+
let viewControllers: [UIViewController] = self.navigationController!.viewControllers
for aViewController in viewControllers {
if aViewController is YourViewController {
self.navigationController!.popToViewController(aViewController, animated: true)
}
}
我更喜欢通用的方式。
我有 UINavigationController 的这个扩展:
extension UINavigationController {
func backToViewController(vc: Any) {
// iterate to find the type of vc
for element in viewControllers as Array {
if "\(element.dynamicType).Type" == "\(vc.dynamicType)" {
self.popToViewController(element, animated: true)
break
}
}
}
}
假设我在导航堆栈中实例化了一个 FOHomeVC class(它是一个 UIViewController)。
所以我会在我的代码中这样做:
self.navigationController?.backToViewController(FOHomeVC.self)
请为 Swift 3.0 使用以下代码:
let viewControllers: [UIViewController] = self.navigationController!.viewControllers as [UIViewController];
for aViewController:UIViewController in viewControllers {
if aViewController.isKind(of: YourViewController.self) {
_ = self.navigationController?.popToViewController(aViewController, animated: true)
}
}
Swift 4.0
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: DashboardVC.self) {
_ = self.navigationController!.popToViewController(controller, animated: true)
break
}
}
这很完美。
我在 UINavigationController
中添加了一个扩展,它可以帮助您找到该控制器是否存在于导航堆栈中。如果是,那么它将被弹出到该控制器,否则您将传递新的控制器以使用 pushController
参数进行推送。
extension UINavigationController {
func containsViewController(ofKind kind: AnyClass) -> Bool {
return self.viewControllers.contains(where: { [=10=].isKind(of: kind) })
}
func popPushToVC(ofKind kind: AnyClass, pushController: UIViewController) {
if containsViewController(ofKind: kind) {
for controller in self.viewControllers {
if controller.isKind(of: kind) {
popToViewController(controller, animated: true)
break
}
}
} else {
pushViewController(pushController, animated: true)
}
}
}
最近 swift
@IBAction func popToConversationsVC(_ sender: UIButton) {
if (self.navigationController != nil) {
for vc in self.navigationController!.viewControllers {
if vc is ConversationsVC {
self.navigationController?.popToViewController(vc, animated: false)
}
}
}
}
从导航堆栈中找到您的视图控制器,如果存在则弹出到该视图控制器
for vc in self.navigationController!.viewControllers {
if let myViewCont = vc as? VCName
{
self.navigationController?.popToViewController(myViewCont, animated: true)
}
}
Swift 4 / Swift 5
for controller in self.navigationController!.viewControllers as Array {
if controller.isKind(of: HomeViewController.self) {
self.navigationController!.popToViewController(controller, animated: true)
break
}
}
我需要使用它,因为在某些情况下应用会崩溃:
if let navVC = self.navigationController {
let views = navVC.viewControllers as Array
for controller in views {
if controller.isKind(of: YourVC.self) {
navVC.popToViewController(controller, animated: true)
return
}
}
}
Swift 5
弹出特定 class 的最新实例,例如 SomeViewController
:
navigationController?.popToViewController(ofClass: SomeViewController.self)
但您需要添加 UINavigationController
扩展名:
extension UINavigationController {
func popToViewController(ofClass: AnyClass, animated: Bool = true) {
if let vc = viewControllers.last(where: { [=11=].isKind(of: ofClass) }) {
popToViewController(vc, animated: animated)
}
}
}
extension UINavigationController {
func popBack(to vc: AnyClass, animated: Bool = true) {
guard let elementFound = (viewControllers.filter { [=10=].isKind(of: vc) }).first else {
fatalError("cannot pop back to \(vc) as it is not in the view hierarchy")
}
self.popToViewController(elementFound, animated: animated)
}
}
没有强制展开的简单且最佳的解决方案是
if let vc = navigationController.viewControllers.filter({[=10=] is YourViewController}).first as? YourViewController {
self.navigationController.popToViewController(vc, animated: true)
}
swift5
let controllers : Array = self.navigationController!.viewControllers
self.navigationController!.popToViewController(controllers[1], animated: true)
我更喜欢 "real generic" 和更实用的方法。
所以我想出了以下 UINavigationController
扩展函数。您还可以将第一个函数用于其他用途,您只需要访问导航堆栈中的特定 VC。
扩展
extension UINavigationController {
func getViewController<T: UIViewController>(of type: T.Type) -> UIViewController? {
return self.viewControllers.first(where: { [=10=] is T })
}
func popToViewController<T: UIViewController>(of type: T.Type, animated: Bool) {
guard let viewController = self.getViewController(of: type) else { return }
self.popToViewController(viewController, animated: animated)
}
}
用法
self.navigationController?.popToViewController(of: YourViewController.self, animated: true)
这应该至少在 Swift 4 和 5 中有效。
Swift 5 @PabloR 的答案在这里:
extension UINavigationController {
func backToViewController(vc: Any) {
// iterate to find the type of vc
for element in viewControllers as Array {
if "\(type(of: element)).Type" == "\(type(of: vc))" {
self.popToViewController(element, animated: true)
break
}
}
}
}
用法:
self.navigationController?.backToViewController(vc: TaskListViewController.self)
对于 Swift 4.0 及更高版本使用过滤器
guard let VC = self.navigationController?.viewControllers.filter({[=10=].isKind(of: YourViewController.self)}).first else {return}
self.navigationController?.popToViewController(VC, animated: true)
这个解决方案对我有用:)
extension UINavigationController {
func backToViewController(_ viewController: AnyClass, animated: Bool) {
guard let viewController = self.viewControllers.first(where: {[=10=].isKind(of: viewController)}) else { return }
self.popToViewController(viewController, animated: animated)
}
}
我改编自以上所有答案。它看起来像 Yakup Ad 答案,因为它的路很短。
- 我通过对参数使用泛型来强制类型,确保您必须只将 UIViewController 传递给此函数。
- 我使用 .first 搜索已经在堆栈中的 viewController。这让我只有一个 VC 然后停止循环。
- 如果你需要定制一些东西,我也会return传递VC。
让我们尽情享受吧。
extension UINavigationController {
func popToViewController<T: UIViewController>(_ viewController: T.Type, animated: Bool) -> T? {
guard let viewController = self.viewControllers.first(where: {[=10=] is T}) else { return nil }
self.popToViewController(viewController, animated: animated)
return viewController as? T
}
}
用法
let poppedVC = self.navigationController?.popToViewController(HomeViewController.self, animated: true)