无法调用'插入'使用BaseCellData

时间:2017-05-23 12:11:37

标签: swift generics

构建Swift代码时出现此错误:

Cannot invoke 'insert' with an argument list of type '(BaseCellData, at: Int)' on the row

当我运行以下代码时:

public class CellDataCollection<T: BaseCellData> {
    private var data = [T]()

    func populate(from data: [T]) {
        self.data = data
        let firstObjectIsHeader = data.first?.isHeader ?? false
        if !firstObjectIsHeader {
            let newEmptyHeader = BaseCellData(isEmptyHeader: true)
            self.data.insert(newEmptyHeader, at: 0)
        }
        // ...
    }
}

我认为因为T是一个BaseCellData,所以可以将一个新的BaseCellData实例添加到T的数组中。可能有什么问题?

3 个答案:

答案 0 :(得分:0)

强制施放newEmptyHeaderT符合我的机器。

public class BaseCellData {
    public var isEmptyHeader = false
    public var isHeader = true
    public init(isEmptyHeader: Bool) {
        self.isEmptyHeader = isEmptyHeader
    }
}

public class CellDataCollection<T: BaseCellData> {
    private var data = [T]()

    func populate(from data: [T]) {
        self.data.append(contentsOf:data)
        let firstObjectIsHeader = data.first?.isHeader ?? false
        if !firstObjectIsHeader {
            let newEmptyHeader = BaseCellData(isEmptyHeader: true)
            // Safer approach
            if let newEmptyHeader = newEmptyHeader as? T {
                self.data.insert(newEmptyHeader, at: 0)
            }
        }
    }
}

答案 1 :(得分:0)

您的T数组是一种特定类型,其中BaseCellData更通用。

例如,假设你有这些课程:

class Animal {}
class Dog: Animal {}
class Cat: Animal {}

你创造了一系列狗,显然你不能添加猫或动物

var dogs = [Dog]
dogs.append(Cat()) // Not allowed
dogs.append(Animal()) // Also not allowed    

所以如果你有一个通用的:

class AnimalCollection<T:Animal> {
    var animals: [T]
}

然后,如果您创建一个集合,则T的类型是您定义为泛型类型的任何类型。所以:

let dogCollection: AnimalCollection<Dog>

阵列属于Dog类型,正如我们在添加动物或猫之前看到的那样是不允许的。

答案 2 :(得分:0)

我通过向所有实现BaseCellType的子类添加构造函数来解决它。这允许我创建一个T实例而不是BaseCellType:

public class CellDataCollection<T: BaseCellData> {
func dataWithLeadingEmptyHeader(from data: [T]) -> [T] {
        var newData = data
        let firstObjectIsHeader = data.first?.isHeader ?? false
        if !firstObjectIsHeader {
            let newEmptyHeader = T(isEmptyHeader: true)
            newData.insert(newEmptyHeader, at: 0)
        }
        return newData
    }    

    func populate(from data: [T]) {
        self.data = dataWithLeadingEmptyHeader(from: data)
        // ...
    }
}

我的基类现在有两个新的内容:

public class BaseCellData: XXX {
    required override public init(isEmptyHeader: Bool) {
        super.init()
        isHeader = true
        self.isEmptyHeader = isEmptyHeader
    }

    public override init() {
        super.init()
    }
}

和子类现在有一个新的init:

public class SelectIconCellData: BaseCellData {
    var iconName: String = ""

    init(text: String, imageName: String) {
        super.init()
        // ...
    }

    required public init(isEmptyHeader: Bool) {
        super.init(isEmptyHeader: isEmptyHeader)
    }
}