首页 文章

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

提问于
浏览
310

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

16 回答

  • 3

    Swift 3.0

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

    它会节省您的时间 .

  • 10
    • 您需要在每个方法之前添加 optional 关键字 .

    • 但请注意,为此, your protocol must be marked with the @objc attribute.

    • 这进一步意味着该协议适用于类而不适用于结构 .

  • 32

    具有协议继承的纯Swift方法:

    //Required methods
    protocol MyProtocol {
        func foo()
    }
    
    //Optional methods
    protocol MyExtendedProtocol: MyProtocol {
        func bar()
    }
    
    class MyClass {
        var delegate: MyProtocol
        func myMethod() {
            (delegate as? MyExtendedProtocol).bar()
        }
    }
    
  • -1

    Here is a concrete example with the delegation pattern.

    设置您的协议:

    @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?()
    
  • 374

    由于有一些关于如何使用 optional modifier@objc attribute 定义可选需求协议的答案,我将举例说明如何使用协议扩展定义可选协议 .

    下面的代码是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*
    

    请注意协议扩展方法可以't invoked by Objective-C code, and worse is Swift team won'解决它 . https://bugs.swift.org/browse/SR-492

  • 7

    如果要使用可选方法, must@objc 属性标记您的协议:

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

    否则,Swift协议的行为类似于其他OO语言上的接口,其中必须实现接口中定义的所有方法 .

  • 31

    在Swift 2及更高版本中,可以添加协议的默认实现 . 这为协议中的可选方法创建了一种新方法 .

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

    它在创建可选协议方法方面不是一个非常好的方法,但是您可以在协议回调中使用结构 .

    我在这里写了一个小小的总结:https://www.avanderlee.com/swift-2-0/optional-protocol-methods/

  • 6

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

    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一起使用的可选协议,将函数声明为变量而不是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)?
    }
    

    然后你可以用“?”检查功能是否已实施

    func returnEntity() -> Health {
        return Human()
    }
    
    var anEntity: Health = returnEntity()
    
    var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))? 
    //"isHealthy" is true
    
  • 32

    为了说明Antoine答案的机制:

    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"
    
  • 31

    从原始问题略微偏离主题,但它 Build 了Antoine的想法,我认为它可能会帮助某人 .

    对于具有协议扩展的结构,您还可以使计算属性可选 .

    您可以在协议上创建属性可选

    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?
    }
    

    我还写了如何做optional properties in Swift protocols on my blog,我将不断更新,以防万一通过Swift 2版本发生变化 .

  • 3

    我想在问 how 之前你可以实现一个可选的协议方法,你应该问 why 你应该实现一个 .

    如果我们将swift协议视为经典面向对象编程中的接口,则可选方法没有多大意义,也许更好的解决方案是创建默认实现,或将协议分成一组协议(可能具有一些继承关系)它们之间)代表协议中可能的方法组合 .

    有关进一步阅读,请参阅https://useyourloaf.com/blog/swift-optional-protocol-methods/,其中提供了关于此问题的出色概述 .

  • -17

    这是一个非常简单的示例,仅适用于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!)
        }
    
     }
    
  • 1

    如果你想在纯swift中执行它,最好的方法是提供一个默认的实现粒度,如果你返回一个Swift类型,例如 struct 与Swift类型

    例如:

    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()
        }
    }
    

    然后你可以实现协议而不定义每个 func

  • 407

    How to create optional and required delegate methods.

    @objc protocol InterViewDelegate:class {
    
        @objc optional func optfunc()  //    This is optional
        func requiredfunc()//     This is required 
    
    }
    
  • 26

    要在swift中定义 Optional Protocol ,您应该在 Protocol 声明之前使用 @objc 关键字并在该协议中使用 attribute / method 声明 . 以下是协议的可选属性示例 .

    @objc protocol Protocol {
    
      @objc optional var name:String?
    
    }
    
    class MyClass: Protocol {
    
       // No error
    
    }
    
  • 12

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

相关问题