不使用@objc在Swift中实现可选协议方法

3

通过在Swift中使用@objc,我们可以在协议内创建可选方法,例如:

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

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

2
你不能这样做,因为它们是特定于ObjC的。最简单的方法是在扩展中提供空的默认实现,然后根据需要进行覆盖。 - BallpointBen
4个回答

22

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

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

extension Opt {
    func optionalFunc() {}
}

使用这个方法,您不需要在符合Opt标准的类中实现optionalFunc(),因为它们已经有了默认实现。


只进行了非常有限的测试,我认为这个不再起作用了! - paul_f
这依然有效。@paul_f 确保你的扩展方法完全匹配委托协议的方法。 - Alexander Sandberg

1

Swift协议不支持可选方法。

Apple文档:

可选协议要求

您可以为协议定义可选要求,这些要求不需要被符合协议的类型实现。可选要求在协议的定义中以可选修饰符作为前缀。可选要求可用于编写与Objective-C互操作的代码。协议和可选要求都必须标有@objc属性。请注意,@objc协议只能被继承自Objective-C类或其他@objc类的类采用。它们不能被结构体或枚举采用。

Apple Protocol Documentation


苹果在许多使用Swift编写的协议中使用关键字“optional”,而不使用@objc。(例如:UITextFieldDelegate)有什么想法吗? - Marcy
我相信UITextFieldDelegate实际上被定义为一个ObjC接口。 - Jake
我认为你可能是对的。我没有看到@interface或Objective-C代码,而是看到了Swift和protocol关键字。所以,我有点困惑于使其工作的机制。谢谢你的回复。 - Marcy

1

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

   //: 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

1
这不是一个可选的协议方法。无论是否被覆盖,总会有一个实现完成,因此它不是可选的。 - Jake

1

协议中可选方法的常见用途是定义委托可以监听的可选回调。这种情况最好使用 protocol + extension 方法(为所有可选方法提供无操作的默认实现)来实现。

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

protocol Storage {
    func read() -> Data
}

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

标准库在 SequenceCollection 和相关类中采用了这种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接