简体   繁体   English

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

[英]Swift protocol implementing another @objc protocol

Using Swift 4, I'm trying to write a custom protocol which provides conformance to an @objc protocol. 使用Swift 4,我试图编写一个自定义协议,该协议提供与@objc协议的一致性。

Some Code 一些代码

More specifically, I have a custom protocol Searchable which provides a simple implementation of the UIKit protocol UISearchBarDelegate , requiring to only implement a single callback for handling search filter changes. 更具体地说,我有一个自定义协议Searchable ,它提供了UIKit协议UISearchBarDelegate的简单实现,只需要实现一个用于处理搜索过滤器更改的回调即可。

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

I provide the delegate implementation in a protocol extension: 我在协议扩展中提供了委托实现:

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

Finally, in another extension I create and install the search bar ( installSearchBar has to be called from viewDidLoad of the concrete view controller): 最后,在另一个扩展中,我创建并安装搜索栏(必须从具体视图控制器的viewDidLoad调用installSearchBar ):

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

The Problem 问题

Unfortunately, the delegate methods of UISearchBarDelegate are not called when the user enters text in the search bar. 不幸的是,当用户在搜索栏中输入文本时,不会调用UISearchBarDelegate的委托方法。 The compiler warns me with this message: 编译器通过以下消息警告我:

Non-'@objc' method 'searchBar(_:textDidChange:)' does not satisfy optional requirement of '@objc' protocol 'UISearchBarDelegate' 非'@objc'方法'searchBar(_:textDidChange :)'不满足'@objc'协议'UISearchBarDelegate'的可选要求

However, I cannot add @objc to the method because this causes the following compiler error: 但是,我无法将@objc添加到该方法,因为这会导致以下编译器错误:

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes @objc只能与类的成员,@ objc协议和类的具体扩展一起使用

The Question 问题

So now my question is: can the desired behavior be implemented in Swift at all, or is it not possible to implement conformance to an @objc protocol in another protocol? 所以现在我的问题是:所需的行为是否可以在Swift中实现,还是不能在另一协议中实现对@objc协议的一致性?

Note 1: I know that this can be implemented using subclass; 注意1:我知道可以使用子类来实现; still I'm looking for a POP version. 我仍然在寻找POP版本。

Note 2: I know there is UISearchController which also helps to simplify implementing search; 注2:我知道有UISearchController ,它也有助于简化实现搜索; I cannot use this class because in my actual code, I have a more complex filter view with other controls -- that's why I use a bare UISearchBar . 我不能使用此类,因为在我的实际代码中,我具有与其他控件一起使用的更复杂的过滤器视图-这就是为什么我使用裸UISearchBar的原因。

This is due to the fact that Obj-C runtime uses Dynamic dispatch (dynamic lookup/message passing) to conforming object to know if it confirms the required method and invoke it. 这是因为,Obj-C运行时使用动态调度(动态查找/消息传递)对符合条件的对象进行了解,以了解其是否确认了所需的方法并调用了它。

Swift protocol extension by default use static dispatch. Swift协议扩展默认情况下使用静态调度。 In a sense, when UISearchBarDelegate passes a message to your class that conforms to this protocol it can't find the extension method as this is static to the protocol. 从某种意义上说,当UISearchBarDelegate向符合此协议的类传递消息时,由于该协议是静态的,因此找不到扩展方法。 And hence your implementation is neither detected by the runtime nor does it work. 因此,运行时既无法检测到您的实现,也无法正常工作。

This is a very deep topic. 这是一个非常深刻的话题。 I don't expect you to be clear with my simple paragraph. 我不希望您用我的简单段落弄清楚。 However, I tried this when Swift Protocol Extension was new (trying to generalize UITableViewDelegate and DataSource) but all in vain. 但是,当Swift协议扩展是新的(试图推广UITableViewDelegate和DataSource)时,我尝试了此操作,但是全部徒劳。 I had to research into why and I can tell you from my experience and research this has to do with Objc messaging passing relying on dynamic dispatch and protocol extension being statically dispatched. 我必须研究原因,并可以从我的经验中告诉您,这与Objc消息传递有关,后者依赖于动态调度和静态协议扩展。

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

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