【问题标题】:Check if optional protocol method is implemented in Swift?检查是否在 Swift 中实现了可选协议方法?
【发布时间】:2015-05-22 14:02:47
【问题描述】:

我有一个快速的协议:

@objc protocol SomeDelegate {

  optional func myFunction()

}

我上过的一门课:

weak var delegate: SomeDelegate?

现在我想检查delegate 是否实现了myFunction

在objective-c中我可以做到:

if ([delegate respondsToSelector:@selector(myFunction)]) { 
...
}

但这在 Swift 中不可用。

编辑:这不同于:What is the swift equivalent of respondsToSelector? 我专注于类协议而不是类。

如何检查我的委托是否实现了可选方法?

【问题讨论】:

标签: ios swift


【解决方案1】:

The Swift Programming Language:

您通过编写检查可选要求的实现 在调用需求名称后的问号, 比如 someOptionalMethod?(someArgument)。可选属性 要求,以及返回值的可选方法要求, 将始终返回适当类型的可选值 被访问或调用,以反映可选的事实 要求可能尚未实现。

因此,目的不是您检查该方法是否已实现,而是您尝试不顾一切地调用它并获得可选的返回。

【讨论】:

  • 我想在调用它之前检查可选方法是否存在。
  • 那么你可能不想使用 Swift。这不是该语言旨在支持的内容。你的实际用例是什么?
  • @confile:查看“重复问题”的所有答案,例如:stackoverflow.com/a/27665147/1187415。它展示了如何首先测试委托是否实现了该方法,然后再调用它。
  • @Tommy 虽然人们应该努力遵循约定,但在某些情况下,知道是否实际实现了可选方法可能会很方便。在我的例子中,可选方法的实现表明插件是否处理某个可选工作。
  • 如果可选方法返回可选类型。如果你真的想知道区别,你可能会有点卡住。
【解决方案2】:

你可以的

if delegate?.myFunction != nil {

}

【讨论】:

  • 重载方法怎么样?我们可以这样做来检查一个特定的吗?
  • 如果函数不是可选的,这会使 Xcode 7.3 Beta 中的编译器崩溃。很奇怪。
  • 这样方法会被调用两次,可能会导致一些意想不到的问题
【解决方案3】:

我通常是这样实现的:

self.delegate?.myFunction?()

如果委托方法返回值:

var result = defaultValue
if let delegateResult = self.delegate?.myFunction?() else {
  result = delegateResult
}

//do something with result

【讨论】:

    【解决方案4】:

    我发现向定义基本默认实现的协议添加扩展是成功的,然后实现该协议的任何类只需要覆盖感兴趣的功能。

        public protocol PresenterDelegate : class {
            func presenterDidRefreshCompleteLayout(presenter: Presenter)
            func presenterShouldDoSomething(presenter: Presenter) -> Bool
        }
    

    然后扩展

        extension PresenterDelegate {
            public func presenterDidRefreshCompleteLayout(presenter: Presenter) {}
            public func presenterShouldDoSomething(presenter: Presenter) -> Bool {
            return true
            }
        }
    

    现在任何需要符合 PresenterDelegate 协议的类都已经实现了所有功能,因此现在可以可选覆盖它的功能。

    【讨论】:

    • 看起来很有用,如果我只能在需要时记住它:-)
    • 是的,但是如果某些代码只有在实现了功能时才需要采取行动,这将如何工作?如果由于协议代码的某些部分调用#selector 而需要@objc,它将无法编译,因为它正在处理UI。嗯。
    【解决方案5】:

    我知道这个问题已有 5 年历史,但我想分享我的发现。我的解决方案适用于 2021 年,XCode 11+,Swift 5。

    假设我想弄清楚函数符号是否遵循 GIDSignInDelegate 协议,并且还想知道 GIDSignInDelegate 的所有可选函数是什么。

    我得看看 GIDSignIn 模块的源代码,是这样的。

    在导入的主模块上单击跳转到定义。它将导致这样的文件:

    复制整行,导入 GoogleSignIn.GIDSignIn 并将其粘贴到 ViewController 或任何 .swift 文件中(并不重要)。

    在 swift 文件中,右键单击导入行 GoogleSignIn.GIDSignIn 的 GIDSignIn 部分并跳转到定​​义。这将带您进入具有所有可用功能的实际模块(未标记为可选的功能可能是存根,这是委托协议中的必需功能):

    从这个文件中,我可以看到有一个作为 GIDSignInDelegate 存根的符号函数和一个作为方法重载实现的可选符号函数。

    我将它用于 GIDSignInDelegate,但您可以使用相同的方法来确定任何函数是否遵循任何委托协议。

    【讨论】:

      【解决方案6】:

      声明

      @objc public protocol nameOfDelegate: class {
          @objc optional func delegateMethod(_ varA: int, didSelect item: Item)
      }
      

      实现

      if let delegate = nameOfDelegate {
           delegate.delegateMethod?(1, didDeselect: node)
      }
      

      【讨论】:

        猜你喜欢
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-07-24
        相关资源
        最近更新 更多