无法重新声明类型

时间:2018-05-31 00:04:55

标签: swift generics

我有一个通用协议TwoWayBindDelegate,它使用通用关联类型来确定函数twoWayBind()的参数

protocol TwoWayBindDelegate: class {

    associatedtype BindType

    func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
}

然后我创建了一个类Reactive<Base: UIView, Type>(符合TwoWayBindDelegate),您必须使用通用Base对其进行初始化。例如:let reactiveSlider = Reacive<UISlider>(slider)

我的问题是,当我扩展Reactive并符合TwoWayBindDelegate时,我收到错误Invalid redeclaration of 'BindType',因为我在两个扩展程序中都声明了BindTypetwoWayBind()。有没有办法可以让两个扩展为TwoWayBindDelegate

提供不同的实现
class Reactive<Base: UIView>: TwoWayBindDelegate {

    public var base: Base

    init(base: Base) {
        self.base = base
    }
}

extension Reactive where Base == UISlider {

    typealias BindType = Float        

    func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?) {
        // implement two way bind for UISlider
    }
}

extension Reactive where Base == UITextField {

    typealias BindType = String        

    func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?) {
        // implement two way bind for UITextField
    }
}

我做了一些研究,发现它可能是一个错误https://bugs.swift.org/browse/SR-5392。是否碰巧有解决方法

1 个答案:

答案 0 :(得分:1)

我不太明白typealias的用途。单独的函数声明足以告诉编译器BindType必须是什么。

我在代码中发现的问题(当然除了缺少的Observable声明)是Reactive类本身不符合TwoWayBindDelegate。为了解决这个问题,我投入了twoWayBind的任意实现。当我这样做,当我删除不必要的typealias声明时,你的代码为我编译:

struct Observable<T> {}

protocol TwoWayBindDelegate: class {
    associatedtype BindType
    func twoWayBind(to observable: Observable<BindType>?, observableChanged: ((BindType) -> ())?)
}

class Reactive<Base: UIView>: TwoWayBindDelegate {
    public var base: Base
    init(base: Base) {
        self.base = base
    }
    func twoWayBind(to observable: Observable<Int>?, observableChanged: ((Int) -> ())?) {
    }
}

extension Reactive where Base == UISlider {
    func twoWayBind(to observable: Observable<Float>?, observableChanged: ((Float) -> ())?) {
    }
}

extension Reactive where Base == UITextField {
    func twoWayBind(to observable: Observable<String>?, observableChanged: ((String) -> ())?) {
    }
}