如何在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
放在方法或属性的前面。