2017-08-29 23 views
0

说我有以下几点:有条件地转换失败

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时并不总是返回真(进入if语句),我不明白为什么。它们从相同的基类继承而来。

编辑:

我猜这是因为类的一般性质。对于调用它的子类,if语句的计算结果为true。

+0

都是为“是”条件要检查的viewController类型等于ContentSelectableTableViewController和第二个条件你铸造的viewController到ContentSelectableTableViewController不同。 – Pushpendra

+0

是的,我知道。这不是问题。问题是为什么这些if语句对通用的一个子类评估为真,而不是另一个。 – horseshoe7

回答

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 { //... } 

然后,重构orig inal post,得到:

@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 
} 

我仍然不完全理解使它失败的语言方面,但这个解决方案的工作原理。

基于协议的程序设计似乎更加SWIFTY反正...