可选只能应用于@objc协议的成员

Zig*_*ong 10 objective-c swift

在这里我在Swift中定义一个协议:

protocol DrawViewProtocol: class{
    optional func drawViewDidEndEditing() // Warning!
}
Run Code Online (Sandbox Code Playgroud)

编译器给了我一个错误.

可选只能应用于@objc协议的成员

所以我所理解的是optional,required只有Objective-C才有用吗?但是,如何定义纯Swift风格的可选必需

Tom*_*ton 36

Swift不允许协议具有可选的要求 - 如果协议声明了某些内容,则需要它.Objective-C长期以来一直有可选要求的想法,当你@objc在声明协议时使用时,Swift会认识到这一点.所以使用@objc是获得你所追求的东西的简单方法.

如果您需要纯Swift解决方案,则需要添加包含方法默认实现的协议扩展.这并不会使这些方法成为可选方法,而是说任何不实现方法的类都将使用默认实现.它们是可选的,因为类不必实现它们,但不是真正可选的,因为这只是因为默认实现可用.

这看起来像这样:

protocol DrawViewProtocol : class{
    func drawViewDidEndEditing()
}

extension DrawViewProtocol {
    func drawViewDidEndEditing() {}
}

class MyClass : DrawViewProtocol {

}

class MyOtherClass : DrawViewProtocol {
    func drawViewDidEndEditing() {
        print("Foo")
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我创建一个MyClass和调用的实例drawViewDidEndEditing(),它将使用默认实现,它不执行任何操作.如果我创建一个实例MyOtherClass,相同的方法调用打印"Foo".

  • UIKit使用Objective-C样式的可选协议要求。 (2认同)

AkB*_*mbe 16

Swift 3Swift 4中使用@objc作为可选原型

@objc protocol YourProtocolName: class {
    @objc optional func yourMethodName()
}
Run Code Online (Sandbox Code Playgroud)


Ame*_*has 5

从苹果的文档: Even if you are not interoperating with Objective-C, you need to mark your protocols with the @objc attribute if you want to specify optional requirements.

Optional Protocol Requirements section文档中查看。


Per*_*mat 5

虽然上面的答案实际上是正确的,但它们并没有为您提供纯粹的 Swift 答案。

在 Swift 中做到这一点的正确方法是实际使用协议:

  • 定义您的第一个协议 A,仅包含所需的属性、方法……您能想到的
  • 使用所谓的“可选”属性定义第二个协议 B
  • 因此,所有需要符合 A 标准的类/协议都将是。
  • 那些需要“可选”合规性的项目可以使用协议 B 的合规性进行扩展。

例子:

protocol MyRequiredProtocol {
    var a: String { get }
    var b: String { get }

    func aMethod()
}

protocol MySoCalledOptionalProtocol {
    var c: String { get }

    func anotherMethod()
}


class MyFirstClass: MyRequiredProtocol {
    var a: String { return "a" }
    var b: String { return "b" }

    func aMethod() {
        // Do something
    }
}

class MySecondClass: MyRequiredProtocol, MySoCalledOptionalProtocol {
    var a: String { return "a" }
    var b: String { return "b" }

    var c: String { return "c" }

    func aMethod() {
        // Do something
    }

    func anotherMethod() {
        // Do something
    }
}
Run Code Online (Sandbox Code Playgroud)