Swift 协议实现另一个@objc 协议 [英] Swift protocol implementing another @objc protocol

查看:42
本文介绍了Swift 协议实现另一个@objc 协议的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 Swift 4,我正在尝试编写一个自定义协议,该协议提供对 @objc 协议的一致性.

Using Swift 4, I'm trying to write a custom protocol which provides conformance to an @objc protocol.

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

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.

@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
}

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

Finally, in another extension I create and install the search bar (installSearchBar has to be called from viewDidLoad of the concrete view controller):

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

问题

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

The Problem

Unfortunately, the delegate methods of UISearchBarDelegate are not called when the user enters text in the search bar. The compiler warns me with this message:

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

Non-'@objc' method 'searchBar(_:textDidChange:)' does not satisfy optional requirement of '@objc' protocol 'UISearchBarDelegate'

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

However, I cannot add @objc to the method because this causes the following compiler error:

@objc 只能与类成员、@objc 协议和类的具体扩展

@objc can only be used with members of classes, @objc protocols, and concrete extensions of classes

问题

所以现在我的问题是:是否可以在 Swift 中实现所需的行为,还是不可能在另一个协议中实现对 @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?

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

Note 1: I know that this can be implemented using subclass; still I'm looking for a POP version.

注意 2:我知道有 UISearchController 也有助于简化实现搜索;我不能使用这个类,因为在我的实际代码中,我有一个更复杂的过滤器视图和其他控件——这就是我使用裸 UISearchBar 的原因.

Note 2: I know there is UISearchController which also helps to simplify implementing search; 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.

推荐答案

这是因为 Obj-C 运行时使用动态调度(动态查找/消息传递)到符合对象来知道它是否确认了所需的方法和调用它.

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.

Swift 协议扩展默认使用静态调度.从某种意义上说,当 UISearchBarDelegate 将消息传递给符合此协议的类时,它无法找到扩展方法,因为这是协议的静态方法.因此,您的实现既不会被运行时检测到,也不会工作.

Swift protocol extension by default use static dispatch. 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. And hence your implementation is neither detected by the runtime nor does it work.

这是一个很深的话题.我不指望你能看懂我简单的段落.然而,当 Swift 协议扩展是新的(试图概括 UITableViewDelegate 和 DataSource)时,我尝试了这个,但都是徒劳的.我必须研究原因,我可以从我的经验和研究中告诉你这与依赖动态调度和静态调度的协议扩展的 Objc 消息传递有关.

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. 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.

这篇关于Swift 协议实现另一个@objc 协议的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆