Swift 中的类和协议继承

Posted

技术标签:

【中文标题】Swift 中的类和协议继承【英文标题】:Class and Protocol Inheritance in Swift 【发布时间】: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。

【问题讨论】:

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

【讨论】:

以上是关于Swift 中的类和协议继承的主要内容,如果未能解决你的问题,请参考以下文章

Swift 中带有选择器的协议扩展

swift中的protocol和OC中protocol的区别

iOS Swift delegate的使用

类和协议的 Swift 类型别名

Swift中结构体和类的区别

Swift中类和结构体