[英]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.