【问题标题】:associated protocol conformance error swift 2.0相关的协议一致性错误 swift 2.0
【发布时间】:2015-10-29 01:15:17
【问题描述】:

我知道this post 和我有同样的问题,但是没有答案而且很旧,所以我想在这里刷新一下。

//: 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?

【问题讨论】:

    标签: generics swift2 swift-protocols


    【解决方案1】:

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

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

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

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

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

    protocol BaseCell {
        func configure(viewmodel: BaseViewModel)
    }
    

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

    【讨论】:

    • 是的,我越看这个,我越觉得这在swift中是不可能的,如果你能有通用接口protocol Something<T>
    【解决方案2】:

    我正在发布到目前为止我想出的更新,一种答案,虽然它并不理想,但我已将配置方法更改为如下所示: 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()
        }
    }
    

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-16
      • 1970-01-01
      相关资源
      最近更新 更多