【问题标题】:Class and Protocol Inheritance in SwiftSwift 中的类和协议继承
【发布时间】:2015-01-16 06:42:09
【问题描述】:

假设我在 Swift 中有一个协议

protocol SearchCompletionProtocol {
    func searchSuccessful(results: [AnyObject])
    func searchCancelled()
}

现在假设我有一个类,并且我想在 init 方法中传入一个参数。限制是我希望这个参数是UIViewController 类型并且还符合SearchCompletionProtocol 协议。我该怎么做呢?以下是我尝试过的一些示例,但它们都不起作用。

class SearchDelegate: UISearchDisplayController, UISearchBarDelegate {

    let completionDelegate: SearchCompletionProtocol

    init<T: SearchCompletionProtocol where T: UIViewController>(completionDelegate: T) {
        self.completionDelegate = completionDelegate
        let _searchBar = UISearchBar()
        super.init(searchBar: _searchBar, contentsController: completionDelegate)
    }
}

我还尝试将协议上的继承限制为仅 UIViewController 类型的类,但这也不起作用。

protocol SearchCompletionProtocol: class, UIViewController {
    func searchSuccessful(results: [AnyObject])
    func searchCancelled()
}

当然,我可以很容易地向这个方法传递两个参数,一个符合搜索协议,一个是 UIViewController 类型,但这似乎不是很 Swifty。

【问题讨论】:

  • 你的构造函数在你调用它的地方是什么样子的?
  • @MartinR 是的,非常接近。但是我会认为这是一个错误的答案,因为它更像是一种黑客行为。是的,它可以编译,是的,它会为您提供最终结果,但它很难看。在此之前,我将只做两个参数。
  • @AlexBrown 我不确定你的意思。由于我没有代码工作,我还没有调用这个构造函数。如果我取出所有泛型并只使用两个参数,它可能看起来像SearchDelegate(completionDelegate: self, viewController: self)
  • 如果您不编译它们,它们在哪些方面不起作用?

标签: ios swift protocols


【解决方案1】:

所以看起来解决这个问题的方法是我删除了我认为它不重要的原始代码。这是我的原始代码

protocol SearchCompletionProtocol {
    func searchSuccessful(results: [RTruck])
    func searchCancelled()
}

class SearchDelegate: UISearchDisplayController, UISearchBarDelegate {
    let completionDelegate: SearchCompletionProtocol

    init<T: SearchCompletionProtocol where T: UIViewController>(completionDelegate: T) {
        self.completionDelegate = completionDelegate
        let _searchBar = UISearchBar()
        super.init(searchBar: _searchBar, contentsController: completionDelegate)
        self.completionDelegate.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
    }
}

这里的问题是我使用了self.completionDelegate.navigationItem。类级别的completionDelegate 的类型只是SearchCompletionProtocol,它不是T 类型。删除self 导致它使用传入的参数,在编译器看来,该参数保证是UIViewController,一切正常。这是工作代码

protocol SearchCompletionProtocol {
    func searchSuccessful(results: [RTruck])
    func searchCancelled()
}

class SearchDelegate: UISearchDisplayController, UISearchBarDelegate {
    let completionDelegate: SearchCompletionProtocol

    init<T: SearchCompletionProtocol where T: UIViewController>(completionDelegate: T) {
        self.completionDelegate = completionDelegate
        let _searchBar = UISearchBar()
        super.init(searchBar: _searchBar, contentsController: completionDelegate)
        completionDelegate.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Search, target: self, action: "showSearchBar")
    }
}

【讨论】:

    【解决方案2】:

    在 Swift 4 中,您可以使用新的 & 符号来实现这一点:

    func foo(vc: UIViewController & SearchCompletionProtocol) {
        vc.searchCancelled()
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多