在函数定义中将泛型类型定义为协议类型

时间:2018-03-23 11:31:13

标签: swift generics swift-protocols

我希望有一个视图函数,它返回与给定类型匹配的第一个UIResponder:

extension UIView {
  func responder<T, Result: UIResponder & T>(ofType: T) -> Result? {
    var parentResponder: UIResponder? = self
    while parentResponder != nil {
      parentResponder = parentResponder?.next
      if let matchingResponder = parentResponder as? Result {
        return matchingResponder
      }
    }
    return nil
  }
}

不幸的是,编译器显示以下错误:

Non-protocol, non-class type 'T' cannot be used within a protocol-constrained type

我的问题很简单:如何告诉编译器T是协议类型?

1 个答案:

答案 0 :(得分:2)

你不需要两个论点,一个就足够了。您还可以为type参数提供默认值,以防编译器推断结果:

extension UIView {
    func findResponder<T>(ofType type: T.Type = T.self) -> T? {
        func find(_ current: UIResponder) -> T? {
            if let result = current as? T { return result }
            guard let next = current.next else { return nil }
            return find(next)
        }
        return find(self)
    }
}

请注意,您不能将T限制为仅作为协议,因为在Swift协议中不是第一类类型。但是你不应该这样做。

我还将方法实现重新组织为更具功能性的风格。

用法:

let dataSource = view.findResponder(ofType: UITableViewDataSource.self)
let navCtrl: UINavigationController = view.findResponder()