相关协议一致性错误swift 2.0

时间:2015-10-29 01:15:18

标签: generics swift2 swift-protocols

我知道this post提出与我相同的问题,但是没有答案和陈旧,所以我认为id在这里刷新它。

//: Playground - noun: a place where people can play
import UIKit

protocol BaseViewModel { }

protocol SomeCellViewModelInterface : BaseViewModel { }
protocol AnotherCellViewModelInterface : BaseViewModel { }

protocol BaseCell {

    typealias T
    func configure(viewmodel: T)
}

//

class someCell : UIView, BaseCell {
    typealias T = SomeCellViewModelInterface
    func configure(viewmodel: T) {
        // awesome
    }
}

class someOtherCell : UIView, BaseCell {
    typealias T = AnotherCellViewModelInterface
    func configure(viewmodel: T) {
        // do stuff
    }
}


// the concrete implementations of viewmodels and actually using this UI is ultimatley in another .framework

class ConcreteSomeCellVM : SomeCellViewModelInterface { }
class ConcreteAnotherCellVM : AnotherCellViewModelInterface { }

var viewModel = ConcreteSomeCellVM()

let views: [UIView] = [someCell(), someOtherCell(), UIView()]

这是我需要的一个基本例子,但它说明了这一点

for v in views {

    // A
    if let cell = v as? someCell {
        cell.configure(viewModel)
    }

    // B
    if let cell = v as? BaseCell {
        cell.configure(viewModel)
    }  
}

Block A有效,但需要知道具体的单元格类,所以如果我有一个包含许多不同单元格的列表,有些我不知道具体类型的单元格会起作用。

B区块抛出此错误:

  

错误:协议' BaseCell'只能用作通用约束,因为它具有Self或关联类型要求

有没有办法可以实现Block B?

2 个答案:

答案 0 :(得分:0)

  

有没有办法可以实现Block B?

我不这么认为。假装您是编译器并考虑如何在BaseCell中为configure创建代码。

  • T是什么类型的?
  • 如何在configure的实例上调用BaseCell,知道它可能真的是someCellsomeOtherCell,每个实例都将参数限制为不同的类型?例如

    func doSomethingWithACell(foo: BaseCell)
    {
        foo.configure(??? what can you put here?)
    }
    

为了实现你真正想要的东西,我认为你需要摆脱类型别名并做出如下声明:

protocol BaseCell {
    func configure(viewmodel: BaseViewModel)
}

在每个课程中,他们都需要处理viewModel类型不正确的情况。

答案 1 :(得分:0)

我发布了迄今为止我提出的更新,一种答案,虽然它不理想我已将配置方法更改为如下所示: func configure<T where T : BaseViewModel>(viewmodel: T)

因此,当我配置这些视图时,我不必知道每个视图的具体类:

 for v in views {    
    if let cell = v as? BaseCell {
        cell.configure(viewModel)
    }
 }

需要注意的是,您的具体单元需要转换视图模型类型:

func configure<T : BaseViewModel>(viewmodel: T) {
    if let vm = viewmodel as SomeCellViewModelInterface {
        vm.doSomething()
    }
}

哪个更好但仍然不理想,因为演员阵容仍然需要在单元格中发生。