Ios Swift泛型:参数为T.Type的函数返回可选的T
我试图编写一系列通用函数,通过传递Ios Swift泛型:参数为T.Type的函数返回可选的T,ios,swift,generics,Ios,Swift,Generics,我试图编写一系列通用函数,通过传递UIViewController类或子类类型,然后返回“found”viewController的实例或nil,对viewController堆栈进行排序。到目前为止,我甚至无法编译这个简单的代码片段: extension UINavigationController { func fhk_find<T: UIViewController>(viewControllerType: T.Type) -> T? {
UIViewController
类或子类类型,然后返回“found”viewController的实例或nil,对viewController堆栈进行排序。到目前为止,我甚至无法编译这个简单的代码片段:
extension UINavigationController {
func fhk_find<T: UIViewController>(viewControllerType: T.Type) -> T?
{
if let viewController = viewControllers.first as? viewControllerType {
return viewController
}
else {
return nil
}
}
}
但是,编译器告诉我,viewControllerType
不是一个类型
我不太确定这里缺少了什么…您需要将
视图控制器强制转换。首先(如果存在)转换为T
,而不是参数viewControllerType
。事实上,您根本不需要使用这个参数;您可以将扩展名修改为以下内容:
extension UINavigationController {
func fhkFindFirst<T: UIViewController>(_: T.Type) -> T? {
for viewController in viewControllers {
if let viewController = viewController as? T {
return viewController
}
}
return nil
}
}
使用fhkFindFirst(…)
查找超类实例:不符合预期
而在以下情况下,fooViewController
是一个UIViewController
对象,并且被错误地识别为BarViewController
,因为BarViewController
对象(在UINavigationController.viewControllers
中)的类型转换成功
class BarViewController : UIViewController { }
let fooViewController = UIViewController()
let barViewController = BarViewController()
let navController = UINavigationController(rootViewController: barViewController)
navController.addChildViewController(fooViewController)
print(navController.fhkFindFirst(fooViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(UIViewController))
/* <__lldb_expr_1533.BarViewController: 0x7fa519e2bd40> <-- "wrong" one */
print(navController.fhkFindFirst(barViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(BarViewController))
/* <__lldb_expr_1533.BarViewController: 0x7fa519e2bd40> */
啊!!我知道这很简单。非常感谢。谢谢你指出“自我vs.动态类型”让我避免了将来的头疼。@StephenNewton很乐意帮忙。还请注意,我更新了扩展方法,使其遵循SwiftcamelCase
方法名称命名约定。@StephenNewton注意我的编辑:只要只搜索UIViewController
的子类实例,上述解决方案就可以正常工作,但如果尝试搜索超类对象(UIViewController
),则将始终在UINavigationController.viewControllers
中返回第一个实例。但是,这应该是可以的,因为您所有的ViewController都应该是UIViewController
@dfri的子类的实例,有什么方法可以防止这种情况发生吗?这是一个非常有趣的边缘案例,特别是如果你有中间类的话。代码>类FooVC:AwesomeVC{…}
,类BarVC:AwesomeVC{…}
,和类AwesomeVC:UIViewController{…}
@edelaney05是的,我们可以解决这个问题;见上面编辑的答案。
class FooViewController : UIViewController { }
class BarViewController : UIViewController { }
let fooViewController = FooViewController()
let barViewController = BarViewController()
let navController = UINavigationController(rootViewController: fooViewController)
navController.addChildViewController(barViewController)
print(navController.fhkFindFirst(fooViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(FooViewController))
/* <__lldb_expr_1582.FooViewController: 0x7fb97840ad80> */
print(navController.fhkFindFirst(barViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(BarViewController))
/* <__lldb_expr_1582.BarViewController: 0x7fb978709340> */
class BarViewController : UIViewController { }
let fooViewController = UIViewController()
let barViewController = BarViewController()
let navController = UINavigationController(rootViewController: barViewController)
navController.addChildViewController(fooViewController)
print(navController.fhkFindFirst(fooViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(UIViewController))
/* <__lldb_expr_1533.BarViewController: 0x7fa519e2bd40> <-- "wrong" one */
print(navController.fhkFindFirst(barViewController.dynamicType) ?? "None found.")
// or: print(navController.fhkFindFirst(BarViewController))
/* <__lldb_expr_1533.BarViewController: 0x7fa519e2bd40> */
extension UINavigationController {
func fhkFindFirst<T: UIViewController>(_: T.Type) -> T? {
for viewController in viewControllers {
if let supClassType = viewController.superclass?.dynamicType where supClassType != T.Type.self {
if let viewController = viewController as? T {
return viewController
}
}
}
return nil
}
}
class FooBarViewController: UIViewController { }
class FooViewController : FooBarViewController { }
class BarViewController : FooBarViewController { }
let fooBarViewController = FooBarViewController()
let fooViewController = FooViewController()
let barViewController = BarViewController()
let navController = UINavigationController(rootViewController: fooViewController)
navController.addChildViewController(barViewController)
navController.addChildViewController(fooBarViewController)
print(navController.fhkFindFirst(FooViewController) ?? "None found.")
/* <__lldb_expr_1582.FooViewController: 0x7fe22a712e40> */
print(navController.fhkFindFirst(BarViewController) ?? "None found.")
/* <__lldb_expr_1582.BarViewController: 0x7fe22a4196a0> */
print(navController.fhkFindFirst(FooBarViewController) ?? "None found.")
/* <__lldb_expr_1582.FooBarViewController: 0x7fe22a70ee60> */