swift 中的可选协议方法,不使用 @objc

Optional Protocol methods in swift without using @objc

在swift中使用@objc,我们可以在协议内部创建一个可选的方法,比如

@objc protocol MyProtocol {
  @objc optional func anOptionalMethod()
}

但是如何在不使用 @objc 的情况下创建可选协议方法?

让我们使用该协议的扩展创建一个可选的协议方法并使用它:

   //: Playground - noun: a place where people can play

   import UIKit

   protocol someProtocol {
     func a()
     func b()
   }

  extension someProtocol {
    func c() {
        print("This is optional protocol method")
     }

    var someProperty: String { 
        return "some optional computed property"
    }
  }

 class A: someProtocol {
   func a() {
       print("a")
    }

   func b() {
      print("b")
   }

   // It's upto you to implement c() functionality, 
   // this is an optional protocol method

   func c() {
      print("I am overriding C functionality")
   }
  }

 let obj = A()
 obj.a()
 obj.b()
 obj.c()
 print(obj.someProperty)

输出:

 a
 b
 I am overriding C functionality
 some optional computed property

Swift 协议不支持可选方法。

Apple 文档:

Optional Protocol Requirements

You can define optional requirements for protocols, These requirements don’t have to be implemented by types that conform to the protocol. Optional requirements are prefixed by the optional modifier as part of the protocol’s definition. Optional requirements are available so that you can write code that interoperates with Objective-C. Both the protocol and the optional requirement must be marked with the @objc attribute. Note that @objc protocols can be adopted only by classes that inherit from Objective-C classes or other @objc classes. They can’t be adopted by structures or enumerations.

Apple Protocol Documentation

您可以通过以下方式定义默认函数实现:

protocol Opt {
    func requiredFunc()
    func optionalFunc()
}

extension Opt {
    func optionalFunc() {}
}

这样你就不必在 类 中实现符合 Opt 的 optionalFunc() ,因为它们已经有了默认实现。

协议中可选方法的一个常见用途是定义委托可以侦听的可选回调。这种情况最好使用 protocol + extension 方法(为可选方法的 tall 提供 do-nothing 默认实现)。

对于其他一些情况,使用多个协议可能更合适:

protocol Storage {
    func read() -> Data
}

protocol MutableStorage: Storage {
    func write(data: Data
}

标准库将此方法用于 SequenceCollection 和朋友。