如何在Swift协议中定义可选的方法?

在Swift中可能吗? 如果没有,那么是否有解决方法呢?

如果你想使用可选的方法,你必须@objc属性标记你的协议:

 @objc protocol MyProtocol { @objc optional func doSomething() } class MyClass : MyProtocol { // no error } 

否则,Swift协议的行为就像其他OO语言的接口一样,必须实现接口中定义的所有方法。

在Swift 2.0中,可以添加一个协议的默认实现。 这在协议中创build了可选方法的新方法。

 protocol MyProtocol { func doSomethingNonOptionalMethod() func doSomethingOptionalMethod() } extension MyProtocol { func doSomethingOptionalMethod(){ // leaving this empty } } 

创build可选的协议方法并不是一个非常好的方法,但是可以在协议callback中使用结构。

我在这里写了一个小小的摘要: http : //www.avanderlee.com/swift-2-0/optional-protocol-methods/

这里涉及的标记协议为“@objc”的其他答案在使用特定于swift的types时不起作用。

 struct Info { var height: Int var weight: Int } @objc protocol Health { func isInfoHealthy(info: Info) -> Bool } //Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C" 

为了声明与swift一起工作的可选协议,将函数声明为variables而不是func。

 protocol Health { var isInfoHealthy: (Info) -> (Bool)? { get set } } 

然后执行协议如下

 class Human: Health { var isInfoHealthy: (Info) -> (Bool)? = { info in if info.weight < 200 && info.height > 72 { return true } return false } //Or leave out the implementation and declare it as: //var isInfoHealthy: (Info) -> (Bool)? } 

你可以使用“?” 检查function是否已经执行

 func returnEntity() -> Health { return Human() } var anEntity: Health = returnEntity() var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))? //"isHealthy" is true 
  • 您需要在每种方法之前添加optional关键字。
  • 但是,请注意,为了这个工作, 你的协议必须用@objc属性标记。
  • 这进一步意味着这个协议将适用于类而不是结构。

Swift 3.0中

 @objc protocol CounterDataSource { @objc optional func increment(forCount count: Int) -> Int @objc optional var fixedIncrement: Int { get } } 

这将节省您的时间。

这是委托模式的具体例子。

设置您的协议:

 @objc protocol MyProtocol:class { func requiredMethod() optional func optionalMethod() } class MyClass: NSObject { weak var delegate:MyProtocol? func callDelegate() { delegate?.requiredMethod() delegate?.optionalMethod?() } } 

将代理设置为一个类并实现该协议。 请参阅可选方法不需要执行。

 class AnotherClass: NSObject, MyProtocol { init() { super.init() let myInstance = MyClass() myInstance.delegate = self } func requiredMethod() { } } 

一个重要的事情是可选的方法是可选的,需要一个“?” 打电话时 提到第二个问号。

 delegate?.optionalMethod?() 

由于有关如何使用可选修饰符@objc属性来定义可选需求协议的一些答案,我将举例说明如何使用协议扩展定义可选协议。

下面的代码是Swift 3. *。

 /// Protocol has empty default implementation of the following methods making them optional to implement: /// `cancel()` protocol Cancelable { /// default implementation is empty. func cancel() } extension Cancelable { func cancel() {} } class Plane: Cancelable { //Since cancel() have default implementation, that is optional to class Plane } let plane = Plane() plane.cancel() // Print out *United Airlines can't cancelable* 

请注意协议扩展方法不能被Objective-C代码调用,更糟糕的是Swift团队不会修复它。 https://bugs.swift.org/browse/SR-492

从原来的问题稍微偏离了主题,但是它提出了安托万的想法,我认为这可能有助于某人。

对于带有协议扩展的结构,您也可以使计算属性为可选属性。

您可以在协议上select一个属性

 protocol SomeProtocol { var required: String { get } var optional: String? { get } } 

在协议扩展中实现伪计算属性

 extension SomeProtocol { var optional: String? { return nil } } 

现在,您可以使用具有或不具有可选属性的结构体

 struct ConformsWithoutOptional { let required: String } struct ConformsWithOptional { let required: String let optional: String? } 

我还写了如何在我的博客中使用Swift协议来完成可选属性,在Swift 2版本中通过更新来更新Swift协议 。

我想在问你如何实现可选的协议方法之前,你应该问为什么你应该实现一个。

如果我们将Swift协议看作经典的面向对象编程中的接口 ,可选的方法没有什么意义,也许更好的解决scheme是创build默认的实现,或者将协议分成一组协议(也许带有一些inheritance关系在它们之间)来表示scheme中可能的方法组合。

如需进一步阅读,请参阅https://useyourloaf.com/blog/swift-optional-protocol-methods/ ,其中提供了一个很好的概述。

这里是一个非常简单的示例,仅适用于swift类,不适用于结构或枚举。 请注意协议方法是可选的,有两个级别的可选链接在玩。 此外,采用该协议的类在其声明中需要@objc属性。

 @objc protocol CollectionOfDataDelegate{ optional func indexDidChange(index: Int) } @objc class RootView: CollectionOfDataDelegate{ var data = CollectionOfData() init(){ data.delegate = self data.indexIsNow() } func indexDidChange(index: Int) { println("The index is currently: \(index)") } } class CollectionOfData{ var index : Int? weak var delegate : CollectionOfDataDelegate? func indexIsNow(){ index = 23 delegate?.indexDidChange?(index!) } } 

如果你想在纯粹的swift中完成,最好的方法是提供一个默认的实现细节,如果你返回一个Swifttypes,比如像Swifttypes的结构

例如:

 struct magicDatas { var damagePoints : Int? var manaPoints : Int? } protocol magicCastDelegate { func castFire() -> magicDatas func castIce() -> magicDatas } extension magicCastDelegate { func castFire() -> magicDatas { return magicDatas() } func castIce() -> magicDatas { return magicDatas() } } 

那么你可以在不定义每个函数的情况下实现协议

为了说明安托万答案的机制:

 protocol SomeProtocol { func aMethod() } extension SomeProtocol { func aMethod() { print("extensionImplementation") } } class protocolImplementingObject: SomeProtocol { } class protocolImplementingMethodOverridingObject: SomeProtocol { func aMethod() { print("classImplementation") } } let noOverride = protocolImplementingObject() let override = protocolImplementingMethodOverridingObject() noOverride.aMethod() //prints "extensionImplementation" override.aMethod() //prints "classImplementation" 

@optional放在方法或属性的前面。