繁体   English   中英

Swift协议实现另一个@objc协议

[英]Swift protocol implementing another @objc protocol

使用Swift 4,我试图编写一个自定义协议,该协议提供与@objc协议的一致性。

一些代码

更具体地说,我有一个自定义协议Searchable ,它提供了UIKit协议UISearchBarDelegate的简单实现,只需要实现一个用于处理搜索过滤器更改的回调即可。

@objc protocol Searchable: class, UISearchBarDelegate {
  @objc func searchFilterChanged(_: String?)
}

我在协议扩展中提供了委托实现:

extension Searchable {
  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
    searchFilterChanged(searchText)
  }
  // .. and some other delegate methods
}

最后,在另一个扩展中,我创建并安装搜索栏(必须从具体视图控制器的viewDidLoad调用installSearchBar ):

extension Searchable where Self: UITableViewController {
  func installSearchBar() {
    let searchBar = UISearchBar()
    searchBar.delegate = self
    tableView?.tableHeaderView = searchBar
  }
}

问题

不幸的是,当用户在搜索栏中输入文本时,不会调用UISearchBarDelegate的委托方法。 编译器通过以下消息警告我:

非'@objc'方法'searchBar(_:textDidChange :)'不满足'@objc'协议'UISearchBarDelegate'的可选要求

但是,我无法将@objc添加到该方法,因为这会导致以下编译器错误:

@objc只能与类的成员,@ objc协议和类的具体扩展一起使用

问题

所以现在我的问题是:所需的行为是否可以在Swift中实现,还是不能在另一协议中实现对@objc协议的一致性?

注意1:我知道可以使用子类来实现; 我仍然在寻找POP版本。

注2:我知道有UISearchController ,它也有助于简化实现搜索; 我不能使用此类,因为在我的实际代码中,我具有与其他控件一起使用的更复杂的过滤器视图-这就是为什么我使用裸UISearchBar的原因。

这是因为,Obj-C运行时使用动态调度(动态查找/消息传递)对符合条件的对象进行了解,以了解其是否确认了所需的方法并调用了它。

Swift协议扩展默认情况下使用静态调度。 从某种意义上说,当UISearchBarDelegate向符合此协议的类传递消息时,由于该协议是静态的,因此找不到扩展方法。 因此,运行时既无法检测到您的实现,也无法正常工作。

这是一个非常深刻的话题。 我不希望您用我的简单段落弄清楚。 但是,当Swift协议扩展是新的(试图推广UITableViewDelegate和DataSource)时,我尝试了此操作,但是全部徒劳。 我必须研究原因,并可以从我的经验中告诉您,这与Objc消息传递有关,后者依赖于动态调度和静态协议扩展。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM