Ios 使用通用枚举和通用协议的Swift类型擦除

Ios 使用通用枚举和通用协议的Swift类型擦除,ios,swift,generics,swift2,swift-protocols,Ios,Swift,Generics,Swift2,Swift Protocols,我曾在Swift中使用过几次类型擦除,但它总是涉及一个通用协议。在本例中,它涉及通用枚举和通用协议,我被难住了 以下是我的通用枚举和通用协议以及必要的扩展: enum UIState<T> { case Loading case Success([T]) case Failure(ErrorType) } protocol ModelsDelegate: class { associatedtype Model var state: UISt

我曾在Swift中使用过几次类型擦除,但它总是涉及一个通用协议。在本例中,它涉及通用枚举和通用协议,我被难住了

以下是我的通用枚举和通用协议以及必要的扩展:

enum UIState<T> {
    case Loading
    case Success([T])
    case Failure(ErrorType)
}

protocol ModelsDelegate: class {
    associatedtype Model
    var state: UIState<[Model]> { get set }
}

extension ModelsDelegate {

    func getNewState(state: UIState<[Model]>) -> UIState<[Model]> {
        return state
    }

    func setNewState(models: UIState<[Model]>) {
        state = models
    }
}
枚举UIState{ 装箱 案例成功([T]) 案例失败(错误类型) } 协议模型LEGATE:类{ 关联型模型 变量状态:UIState{get set} } 扩展模型LEGATE{ func getNewState(状态:UIState)->UIState{ 返回状态 } func setNewState(型号:UIState){ 状态=模型 } } 这是我的类型擦除泛型类:

class AnyModelsDelegate<T>: ModelsDelegate {
    var state: UIState<[T]> {

        get { return _getNewState(UIState<[T]>) }  // Error #1
        set { _setNewState(newValue) }
    }

    private let _getNewState: ((UIState<[T]>) -> UIState<[T]>)
    private let _setNewState: (UIState<[T]> -> Void)

    required init<U: ModelsDelegate where U.Model == T>(_ models: U) {
        _getNewState = models.getNewState
        _setNewState = models.setNewState
    }
}
class anymodelselegate:modelselegate{
变量状态:UIState{
获取{return _getNewState(UIState)}//错误#1
集合{u setNewState(newValue)}
}
private let_getNewState:((UIState)->UIState)
私有let_setNewState:(UIState->Void)
必需的初始化(U模型:U){
_getNewState=models.getNewState
_setNewState=models.setNewState
}
}
我得到以下错误(它们在代码示例中标记):

错误#1:

无法将类型为“(UIState).type”(又名“UIState.type”)的值转换为预期的参数类型“UIState”(又名“UIState”)


我已经在这方面工作了一段时间,在这段代码上有相当多的变体“几乎奏效”。错误总是与getter有关。

导致此错误的问题是,在这一行中,您试图将类型作为参数传递,而不是该类型的实例:

get { return _getNewState(UIState<[T]>) }
另外,如果您的
getNewState
setNewState(u:)
协议扩展中的函数仅用于将
状态的获取和设置转发给类型erasure–您可以通过完全删除它们来简化代码,并在类型erasure的
init
中使用闭包表达式:

_getNewState = { models.state }
_setNewState = { models.state = $0 }
(它们通过捕获对
模型的引用来工作,有关更多信息,请参阅)

最后,我怀疑您的意思是在整个代码中引用
UIState
而不是
UIState
,因为在本例中
T
引用了数组中的元素,而您的
.Success
案例将该元素作为关联值(除非您希望在此使用2D数组)

总而言之,通过上述建议的更改,您将希望您的代码如下所示:

enum UIState<T> {
    case Loading
    case Success([T])
    case Failure(ErrorType)
}

protocol ModelsDelegate: class {
    associatedtype Model
    var state: UIState<Model> { get set }
}

class AnyModelsDelegate<T>: ModelsDelegate {
    var state: UIState<T> {
        get { return _getNewState() }
        set { _setNewState(newValue) }
    }

    private let _getNewState: () -> UIState<T>
    private let _setNewState: (UIState<T>) -> Void

    required init<U: ModelsDelegate where U.Model == T>(_ models: U) {
        _getNewState = { models.state }
        _setNewState = { models.state = $0 }
    }
}
枚举UIState{ 装箱 案例成功([T]) 案例失败(错误类型) } 协议模型LEGATE:类{ 关联型模型 变量状态:UIState{get set} } 类anymodelselegate:modelselegate{ 变量状态:UIState{ 获取{return\u getNewState()} 集合{u setNewState(newValue)} } 私有let_getNewState:()->UIState 私人出租_setNewState:(UIState)->Void 必需的初始化(U模型:U){ _getNewState={models.state} _setNewState={models.state=$0} } }
您正在将一个类型传递给一个获取该类型实例的方法我有点困惑为什么
getNewState
函数接受输入,它肯定应该是
()->UIState
?虽然如果您的
getNewState
setNewState
函数仅用于将获取和设置转发到您的类型擦除,它们不是必需的,因为您可以直接在带有闭包的类型擦除中执行此操作(即
\u getNewState={models.state}
\u setNewState={models.state=$0}
)是的,我对此也有点困惑:)。它接受一个输入,因为最初我在它不接受输入时出错。让我试着重构。谢谢,就这样。请张贴你的答案。太好了。非常感谢。是的,我不想要2D数组。这对我来说是个错误,因为我正在努力克服这些错误。@damianesteban很乐意帮忙:)
enum UIState<T> {
    case Loading
    case Success([T])
    case Failure(ErrorType)
}

protocol ModelsDelegate: class {
    associatedtype Model
    var state: UIState<Model> { get set }
}

class AnyModelsDelegate<T>: ModelsDelegate {
    var state: UIState<T> {
        get { return _getNewState() }
        set { _setNewState(newValue) }
    }

    private let _getNewState: () -> UIState<T>
    private let _setNewState: (UIState<T>) -> Void

    required init<U: ModelsDelegate where U.Model == T>(_ models: U) {
        _getNewState = { models.state }
        _setNewState = { models.state = $0 }
    }
}