Swift的意外结果是运营商

时间:2015-08-10 20:17:40

标签: swift generics types

根据下面的代码,我试图了解这段代码出错的地方。 在下面的代码中,我试图在UITabBarController的viewControllers属性中找到特定类的UIViewController,该属性声明为:

var viewControllers: [AnyObject]?

所以我定义了两个UIViewController子类并将它们填充到viewControllers数组并运行两个不同的方法来提取它们“viewControllerInfo:”“”viewControllerInfo2“。 两者都产生相同的结果。

我的理解是: if let x as? T将评估true并将x指定为“T”类型(如果它是同一个类)。 就像if x is T一样。

知道为什么评估会像这样吗?

class VC1: UIViewController {}

class VC2: UIViewController {}

let tabBar = UITabBarController()
tabBar.viewControllers = [VC1(), VC2()]

extension UITabBarController {

    public func viewControllerInfo<T: UIViewController>(ofType: T.Type) -> (viewController: T,index: Int)? {
        if let tabViewControllers = self.viewControllers{
            for  (idx, maybeVCTypeT) in enumerate(tabViewControllers) {
                if let viewController = maybeVCTypeT as? T {
                    return (viewController, idx)
                }
            }

        }
        return nil
    }

    public func viewControllerInfo2<T: UIViewController>(ofType: T.Type) -> (viewController: T,index: Int)? {
        if let tabViewControllers = self.viewControllers{
            for  (idx, maybeVCTypeT) in enumerate(tabViewControllers) {
                if maybeVCTypeT is T {
                    return (maybeVCTypeT as! T, idx)
                }
            }

        }
        return nil
    }


}

以下所有测试最终会得到完全相同的结果: “&lt; __ lldb_expr_89。 VC1 :0x7f85016079f0&gt;”

if let (vc, idx) = tabBar.viewControllerInfo(VC1.self) {
    println(vc)
}

if let (vc, idx) = tabBar.viewControllerInfo(VC2.self) {
    println(vc)
}

if let (vc, idx) = tabBar.viewControllerInfo2(VC1.self) {
    println(vc)
}

if let (vc, idx) = tabBar.viewControllerInfo2(VC2.self) {
    println(vc)
}

我怀疑枚举(x),因为没有它我得到了预期的结果:

if testVC1 is VC2 {
    println("\(testVC1) is \(VC2.self)")
}

以上代码会产生警告:

  

从'VC1'转换为不相关的类型'VC2'总是失败   这就是我想用枚举来实现的......

enter image description here

*****************编辑*****************

实际上,在运行以下完美运行的代码后,我对枚举的怀疑被解散了。

let myArray: [AnyObject] = [VC2(), VC1()]
for (idx, x) in enumerate(myArray) {
    println(x)
    if let xAsVC1 = x as? VC1 {
        println("\(x) is supposed to be \(VC1.self)")
//"<__lldb_expr_155.VC1: 0x7fc12a9012f0> is supposed to be __lldb_expr_155.VC1"

    }

    if x is VC2 {
        println("\(x) is supposed to be \(VC2.self)")
//"<__lldb_expr_155.VC2: 0x7fc12a900fd0> is supposed to be __lldb_expr_155.VC2"

    }
}

1 个答案:

答案 0 :(得分:0)

这似乎是由通用约束引起的,我认为是一个错误(http://www.openradar.me/22218124)。删除泛型约束,或使其成为非ObjC类(例如AnyObject)似乎解决了这个问题:

public func viewControllerInfo<T>(ofType: T.Type) -> (viewController: T,index: Int)? {

您也可以替换:

            if maybeVCTypeT is T {

使用:

            if maybeVCTypeT.isKindOfClass(T) {

这似乎有效。