1

我知道这篇文章与我有同样的问题,但是没有答案而且很旧,所以我想在这里刷新它。

//: 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)
    }  
}

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

块 B 抛出此错误:

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

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

4

2 回答 2

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

这更好但仍然不理想,因为演员仍然需要在牢房中进行。

于 2015-11-02T00:08:17.397 回答
0

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

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

  • T是什么类型的?
  • 您如何调用一个知道它可能真的是 a或 aconfigure的实例,其中每个都将参数限制为不同的类型?例如BaseCellsomeCellsomeOtherCell

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

为了实现你真正想要的,我认为你需要摆脱类型别名并像这样声明:

protocol BaseCell {
    func configure(viewmodel: BaseViewModel)
}

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

于 2015-10-29T10:46:56.400 回答