如何在Swift中使用可选方法委托协议?

时间:2016-02-02 21:38:13

标签: swift

假设我有一个名为public static class FSharpOption { public static FSharpOption<T> Create<T>(T value) { return new FSharpOption<T>(value); } public static bool IsSome<T>(this FSharpOption<T> opt) { return FSharpOption<T>.get_IsSome(opt); } public static bool IsNone<T>(this FSharpOption<T> opt) { return FSharpOption<T>.get_IsNone(opt); } } 的协议,其中包含一个名为MyProtocol的可选方法:

opt()

我还有一个名为@objc protocol MyProtocol { func req() -> Int; optional func opt() -> Int; }的包装类:

MyProtocolWrapper

在方法@objc class ProtocolWrapper : NSObject, MyProtocol{ let delegate : MyProtocol init(delegate : MyProtocol){ self.delegate = delegate } func req() -> Int { //doSomeWorkBeforeReq let r = delegate.req() //doSomeWorkAfterReq return r } func opt() -> Int { return delegate.opt?() //compiler error because Int? is required as return type } }中,如何返回ProtocolWrapper.opt()可能返回且仍符合delegate.opt?()协议的可选值?

感谢您的帮助,

Jair Jr

2 个答案:

答案 0 :(得分:1)

我看到了3种可能的解决方案:

  1. 使可选方法的结果也可选,因此您应将optional func opt() -> Int替换为optional func opt() -> Int?
  2. ProtocolWrapper返回默认值。将return delegate.opt?()替换为返回delegate.opt?() ?? 00就是例如。
  3. (我更喜欢这个选项)创建纯swift协议并实现扩展。
  4. 替换

    @objc protocol MyProtocol {
        func req() -> Int;
    
        optional func opt() -> Int;
    }
    

    protocol MyProtocol {
        func req() -> Int
    
        func opt() -> Int
    }
    
    extension MyProtocol {
        //default implementation here
        func opt() -> Int {
            return 0
        }
    }
    

    P.S。如果您继承自NSObject,则无需在课前编写@objc

    P.P.S。如果您使用选项3,则可以创建纯swift类(不包含NSObject@objc

答案 1 :(得分:1)

首先直接解决您的问题:

  

如何返回delegate.opt?()可能返回的可选值,并且仍然符合MyProtocol协议?

要使req()传播可选值,必须将其声明为返回可选值。 req()实现包含返回Int?的语句,但这并未改变将请求声明为Int的事实。

在这里你的例子中包含一些主要的奇怪之处并不值得,这些奇怪之处都没有本身的无效,但肯定会引起混乱。

  • 您似乎尝试使用相同的协议(MyProtocol)用于两个不同的目的。虽然它会非常干净&#34;统一您的公共和私人接口&#39;将名称合并为一个,这实际上并没有为您的代码带来任何好处(您发布的问题是一个很好的例子)。

    @objc protocol MyProtocol {
        func req() -> Int?
    }
    @objc protocol MyProtocolOptionals {
        optional func req() -> Int
    }
    @objc class ProtocolWrapper : NSObject, MyProtocol {
        let delegate : MyProtocolOptionals
        func opt() -> Int? { return delegate.opt?() }
    }
    
  • 一般来说,Objective-C协议(包括optional属性)在Swift中实现,主要是为了围绕它们设计的旧代码库。理想情况下,新代码将采用Swift的本机语义。例如,optional方法的替代方案是协议扩展,它提供方法的默认实现,以符合不声明自己的类型:

    protocol MyProtocolOptionals {
        func req() -> Int?
    }
    extension MyProtocolOptionals {
        func req() -> Int? { return nil }
    }
    
    @objc MyNonImplementing: MyProtocolOptionals {
    }
    
    @objc MyImplementing: MyProtocolOptionals {
        func req() -> Int? { return true.hashValue }
    }