这段代码让我很困扰。下面,我试图在 NavigationController 的堆栈中找到特定类型的 ViewController 的第一个实例。简单的。但是当我找到它时,我必须将它转换为我刚刚寻找的类型,这对我来说似乎是多余的。
func popToFirstViewController<T:UIViewController>(ofType type:T.Type, animated:Bool) -> T? {
guard let foundViewController = viewControllers.first(where: { $0 is T }) as? T else {
return nil
}
self.popToViewController(foundViewController, animated:animated)
return foundViewController
}
我唯一能想到的就是这个......
func popToFirstViewController<T:UIViewController>(ofType type:T.Type, animated:Bool) -> T? {
guard let foundViewController = viewControllers.flatMap({ $0 as? T }).first() else {
return nil
}
self.popToViewController(foundViewController, animated:animated)
return foundViewController
}
...但我反复发现像这样使用 flatMap
会使阅读代码的人感到困惑,并且正如下面评论中正确指出的那样,它会遍历整个集合,而 first
不会那样做。
那么还有其他方法可以解决这个问题吗?
最佳答案
您可以使用case patterns 来选择您感兴趣的类型的 viewController,然后弹出并返回您找到的第一个:
extension UINavigationController {
func popToFirstViewController<T:UIViewController>(ofType type:T.Type, animated:Bool) -> T? {
for case let vc as T in viewControllers {
self.popToViewController(vc, animated: animated)
return vc
}
return nil
}
}
示例:
使用 OrangeViewController
中的按钮返回堆栈中较早的 GreenViewController
:
@IBAction func popToGreen(_ sender: UIButton) {
let greenVC = self.navigationController?.popToFirstViewController(
ofType: GreenViewController.self,
animated: true
)
// Modify a property in GreenViewController that
// will be moved into a label in viewWillAppear
greenVC?.labelText = "Returned here from Orange"
}
popToLastViewController(ofType:animated:)
您可能还希望一个函数弹出到某个类型的最新 viewController。这很容易通过简单的修改实现(添加 .reversed()
):
func popToLastViewController<T:UIViewController>(ofType type:T.Type, animated: Bool) -> T? {
for case let vc as T in viewControllers.reversed() {
self.popToViewController(vc, animated: animated)
return vc
}
return nil
}
关于swift - 你们都可以在集合中找到一个类型的第一个实例,并将该实例作为具体类型返回吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49162574/