这段代码困扰我。下面,我试图在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
不这样做。
那么还有另一种解决这个问题的方法吗?
答案 0 :(得分:1)
我赞成合并T
和lazy
以获得有条件地投射到func popToFirstViewController<T:UIViewController>(ofType type:T.Type, animated:Bool) -> T? {
guard let foundViewController = viewControllers.lazy.flatMap({ $0 as? T }).first {
return nil
}
self.popToViewController(foundViewController, animated:animated)
return foundViewController
}
的行为,消除不匹配,不枚举整个数组:
flatMap
至于那些阅读代码的人会感到困惑:&#34; cols
是相当惯用的Swift,与upcoming rename to compactMap
相比不那么模糊。如果您所在环境中的读者确实遇到问题,您可以随时编写一个小帮手(通用或非通用),以更清晰的名称执行相同的工作。
答案 1 :(得分:1)
您可以使用案例模式选择您感兴趣的类型的viewControllers,然后弹出并返回您找到的第一个:
SELECT CON
FROM
(
SELECT 1 as SEQ, 0 as NR, NAME ,TEMP.CON1 as CON
FROM (
SELECT NAME, CONCAT(NAME,'(', LEFT(OCCUPATION, 1),')') AS CON1
FROM OCCUPATIONS
ORDER BY NAME -- don't need
) AS TEMP
UNION
SELECT 2, NR, null, TEMP2.CON2
FROM (
SELECT COUNT(*) AS NR, CONCAT('THERE ARE A TOTAL OF ', COUNT(OCCUPATION),' ', OCCUPATION, 's') AS CON2
FROM OCCUPATIONS
GROUP BY OCCUPATION
ORDER BY NR, OCCUPATION -- don't need
) AS TEMP2 ) T
ORDER BY SEQ, NR, NAME, CON
示例:强>
使用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"
}
强>
您可能还希望将函数弹出到类型的最新viewController。只需简单修改(添加popToLastViewController(ofType:animated:)
):
.reversed()