通用视图控制器的有条理转换失败

时间:2017-08-29 12:26:00

标签: ios swift casting

说我有以下内容:

class ContentSelectableViewController<T: NSManagedObject> : UIViewController { //... }

class PersonSelectionViewController: ContentSelectableViewController<Person> { // ... }

class PlaceSelectionViewController: ContentSelectableViewController<Place> { // ... }  

然后在其中一个子类的实例中,我有一些代码:

if let navCtrl = self.navigationController {


    for viewController in navCtrl.viewControllers.reversed() {

        if viewController is ContentSelectableViewController {
            log.info("Worked for \(viewController.description)")
        }

        if let vc = viewController as? ContentSelectableViewController {
            // This should be equivalent to the above.
        }
    }
}

我的问题是,当我的堆栈中充满了这个通用基类的子类时,在检查它们是否为ContentSelectableViewController类型时,它并不总是返回true(进入if语句)不明白为什么。它们继承自相同的基类。

编辑:

由于班级的一般性质,我猜测它。对于调用它的子类,if语句的计算结果为true。

1 个答案:

答案 0 :(得分:0)

因此,它实际上与尝试键入检查泛型类有关。它适用于一个而不是另一个,因为进行调用的人隐式添加了它的类型。

即。 (伪SWIFT)

if viewController is ContentSelectableViewController<Person> { //... }

我所做的是定义一个最终使这些ContentSelectableViewController<T>可选的协议:

enum ContentSelectionRole: Int {
    case none = 0 // no selection going on right now.
    case root  // i.e. the one wanting content
    case branch // an intermediary.  think of a folder when looking for a file
    case leaf  // like a file
}

enum ContentSelectability: Int {
    case noSelections = 0
    case oneSelection = 1
    case multipleSelections = 2
}

protocol ContentSelection {

    var selectedObjects: [NSManagedObject] { get set }
    var selectionRole: ContentSelectionRole { get set }
    var selectionStyle: ContentSelectability { get set }
    func popToSelectionRootViewController() -> Bool
    func willNavigateBack(from viewController: UIViewController)
}

制定定义:

class ContentSelectableViewController<T: NSManagedObject> : UIViewController, ContentSelection { //... }

然后,重构原帖,得到:

@discardableResult func popToSelectionRootViewController() -> Bool {

    if let navCtrl = self.navigationController {

        for viewController in navCtrl.viewControllers.reversed() {

            if let vc = viewController as? ContentSelection {
                if vc.selectionRole == .root {

                    vc.willNavigateBack(from: self)
                    navCtrl.popToViewController(viewController, animated: true)
                    return true
                }
            }
        }
    }

    return false
}

我仍然不太了解使其失败的语言方面,但此解决方案有效。

无论如何,基于协议的编程似乎更加快速......