T不同的通用对象的异构数组

时间:2019-01-24 15:18:28

标签: swift generics collections

这是我的类BaseSection实现Collection的方式,它看起来像这样:

class BaseSection<T:Equatable> {

var items:[T]?

required init(items:[T]){
   self.items = items
  }
}

let sectionTop = BaseSection<TopItem>(items:["foo","bar","yo"])
let sectionBottom = BaseSection<BottomItem>(items:["foo","bar","yo"])

在此演示中,我正在构造一部分Equatable的字符串对象,但是我的项目构造对象具有一个String属性 此处未列出收集实现。 我需要将两个对象都放在数组中,即使它们的基类相同,也不能这样做。

let sections = [sectionTop, sectionBottom]
heterogeneous collection literal could only be inferred to '[Any]' add explicit type annotation....
我在许多解决方案上争取了数小时的努力,但在这里却无法实现我的目标。 任何帮助将不胜感激

Edit: I have uploaded the sample code to gitHub so you can get a better grasp of what im doing 

github Link

2 个答案:

答案 0 :(得分:2)

快速自定义通用类型中的

becos都是不变的,这意味着BaseSection<TopItem>BaseSection<BottomItem>没有关系,因此两者的唯一共同类型是Any,您可以点击链接在评论中以获取更多信息,作为摘要

  1. 数组/ Dict是协方差
  2. 闭包参数类型为协方差,闭包返回类型为协方差
  3. 自定义通用类型是不变的

另外,数组/字典是结构,这意味着它们是按值传递的,因此将它们视为协方差是安全的

答案 1 :(得分:2)

您似乎要构建的是一种随着数据变化自动执行表视图变化的机制。很常见的。我强烈建议您查看ListDiff,这是计算更改的有用起点。 (在我自己的代码中,我使用了重写版本的ListDiff,因此此处的示例未经测试,但应该非常接近。)

目标是创建一组更新操作(从ListDiff示例复制):

import ListDiff

extension Int : Diffable {
    public var diffIdentifier: AnyHashable {
        return self
    }
}
let o = [0, 1, 2]
let n = [2, 1, 3]
let result = List.diffing(oldArray: o, newArray: n)
// result.hasChanges == true
// result.deletes == IndexSet(integer: 0)
// result.inserts == IndexSet(integer: 2)
// result.moves == [List.MoveIndex(from: 2, to: 0), List.MoveIndex(from: 1, to: 1)]
// result.changeCount == 4

这里重要的是您要进行一系列的删除,插入和移动操作。您可以通过以下几行将其应用于表格视图:

extension UITableView {
    func applyChanges(from changeset: Result, forSection section: Int = 0) {
        beginUpdates()

        let deletes = changeset.deletes.map { IndexPath(row: $0, section: section) }
        deleteRows(at: deletes, with: .bottom)

        let inserts = changeset.deletes.map { IndexPath(row: $0, section: section) }
        insertRows(at: inserts, with: .none)

        for move in changeset.moves {
            guard !changeset.deletes.contains(move.from) else { continue }
            moveRow(at: IndexPath(row: move.from, section: section), 
                    to: IndexPath(row: move.to, section: section))
        }

        endUpdates()
    }
}

这里的关键是动画,您只需要索引路径。您实际上并不需要数据。因此,计算索引路径并传递它们。无需泛型。