Swift 协议比较的解决方法

Swift workaround for protocols comparison

我知道比较协议没有任何意义,但我的情况取决于我之前的选择和决定。 table 视图的数据源是一个 RowViewModel 数组。

protocol RowViewModel {}

那里(还)没有任何东西可以使它甚至符合 Equatable。 然后我的 table 有不同的单元格,所有单元格都实现了该协议:

func getCells() -> [RowViewModel] {
    var rows = [RowViewModel]()
    rows.append(Cell1ViewModel())
    rows.append(Cell2ViewModel())
    rows.append(Cell3ViewModel())

    return rows
}

单元格的视图模型:

class Cell1ViewModel: RowViewModel {
    var cellTitle: String
    ...
}

这个结构很方便,但现在它让我感到困惑,因为我现在需要计算增量以发送特定的 tableView 索引以插入/删除行。要计算增量,我需要 RowViewModel 符合 Equatable,这是可能的,但似乎是违背使用此方法的初始点的解决方法。我想做这样的事情:

let oldList = rows
let newList = getCells()

let deltaAdded = newList.filter { !oldList.contains([=14=]) }.compactMap { newList.firstIndex(of: [=14=]) }
let deltaRemoved = oldList.filter { !newList.contains([=14=]) }.compactMap { oldList.firstIndex(of: [=14=]) }

此处的最佳做法是什么?有没有办法为符合 RowViewModel 的具体类型编写比较函数?

正如我在评论中所说,你会得到类似的东西:

class CellViewModel1: Equatable {

    // classes need explicit equatable conformance.
    static func == (lhs: CellViewModel1, rhs: CellViewModel1) -> Bool {
        // your implementation
        return true
    }

}

enum RowViewModel: Equatable { 
    
    // enum automatically is Equatable as long as all cases have Equatable associated types
    case cell1(CellViewModel1)

}

func test() {
    let oldList = [RowViewModel]()
    let newList = [RowViewModel]()

    let deltaAdded = newList.filter { !oldList.contains([=10=]) }.compactMap { newList.firstIndex(of: [=10=]) }
    let deltaRemoved = oldList.filter { !newList.contains([=10=]) }.compactMap { oldList.firstIndex(of: [=10=]) }
}

请注意枚举和 ViewModel 都必须符合 Equatable。 仍然不能 100% 确定这是否符合您的需要。