【问题标题】:Reference to class that conforms to a protocol对符合协议的类的引用
【发布时间】:2016-02-21 10:39:59
【问题描述】:

假设我有一个如下所示的协议:

protocol Foo {
    var bar: Bool { get set }
}

现在我有了符合 Foo 协议的视图控制器;

class FooViewController: UIViewController, Foo {
    ...
}

在另一个班级我想做这样的事情:

class FooClass {

    var viewController: UIViewController? // this should conform to Foo protocol

    func setViewController(viewController: UIViewController) {
        if let fooVC = viewController as? Foo {
            // viewController implements Foo protocol
            self.viewController = fooVC
        } else {
            print("ViewController does not conform to Foo protocol")
        }
    }
}

在 Objective-C 中,我会有一个类似的引用:UIViewController<Foo> *vc 表示 vc 是符合 Foo 协议的 UIViewController 类的对象。有 Swift 等价物吗?

编辑:我猜是not possible :(

【问题讨论】:

    标签: swift protocols


    【解决方案1】:

    警告:此解决方案可能会变得非常痛苦。

    作为一种解决方法,您可以使用协议组合并最终使用扩展

    在您的示例中,您可能只对UIViewController 符合的UIResponder 协议方法感兴趣。

    typealias FooController = protocol<UIResponder, Foo>
    
    class FooClass {
    
      var viewController: FooController?
    
      func setViewController(viewController: FooController) {
        // viewController implements UIResponder and Foo protocols
      }
    }
    

    但是UIViewController 具有不符合任何协议的属性和方法。在这种情况下,您可以创建一个包含您想要的方法的协议并扩展UIViewController

    protocol ViewEvent {
      func viewWillAppear(animated: Bool)
      func viewDidAppear(animated: Bool)
      func viewWillDisappear(animated: Bool)
      func viewDidDisappear(animated: Bool)
    }
    
    extension UIViewController: ViewEvent {}
    
    typealias FooController = protocol<UIResponder, ViewEvent, Foo>
    

    【讨论】:

      【解决方案2】:

      这是解决方案:

      typealias FooController = UIViewController & Foo
      
      class FooClass {
      
          var viewController: FooController?
      
          func setViewController(viewController: FooController) {
              self.viewController = viewController
          }
      }
      

      【讨论】:

        【解决方案3】:

        我明白你的意思。

        我认为您不能声明给定类类型的变量并且符合协议。

        但是,如果您只需要检查 viewController 是否符合 Foo 协议(并且您实际上不需要使用在 Foo 中声明的 bar 属性),那么您可以这样做。

        func setViewController(viewController: UIViewController) {
            if viewController is Foo {
                self.viewController = viewController
            } else {
                print("ViewController does not conform to Foo protocol")
            }
        }
        

        【讨论】:

          【解决方案4】:

          您可以定义为viewController:Foo?

          根据我们的评论,您应该使用if let fooVC = viewController as? FooViewController。如果您可以选择将 viewController 绑定到 Foo ,那么将其分配给 UIViewController 实例将不起作用。

          【讨论】:

          • 那我就不能使用UIViewController的属性和方法了
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-05-19
          • 1970-01-01
          • 2019-11-23
          • 1970-01-01
          相关资源
          最近更新 更多