无法使用泛型类型的参数列表调用方法

时间:2018-12-20 08:19:21

标签: ios swift generic-programming

我有ListDataSource,它管理以下所有模型列表ListDataModel

protocol Serializable {} // Empty protocol

protocol AncestorListDataModel {}

protocol ListDataModel: AncestorListDataModel {
  associatedtype T: Serializable
  var items: [T] { get }
}

class BaseListDataModel<T>: ListDataModel where T: Serializable {
  ...
}

class BaseListDataSource: NSObject {
  private var listModels: [String: AncestorListDataModel] = [:]
  private(set) var modelMapping: [String: Serializable.Type] = [:]
  ...

  func getModel<T>(of type: T.Type, at index: Int) -> T? where T: Serializable {
    if let models = self.listModels[String(describing: T.self)] as? BaseListDataModel<T> {
        if index < 0 && index >= models.items.count {
            return nil
        }

        return models.items[index]
    }
    return nil
  }
}

假设我有

class Person: Serializable {}

我在类似的地方打电话给BaseListDataSource

let dataSource = BaseListDataSource()
...

// Retrieve meta class type Person
if let personType = dataSource.modelMapping("Person") {
  // I want to get the first Person element in the Person list which I stored in dataSource
  let person = dataSource.getModel(of: personType, at: 0)
}

我收到错误消息
Cannot invoke 'getModel' with an argument list of type '(of: Serializable.Type, at: Int)'
在Swift中,有没有办法像上面那样将类类型传递给方法getModel(of:_at:_)

更新:我找到了一种更改答案代码的方法,并编辑了问题代码语法。

1 个答案:

答案 0 :(得分:0)

我花了几天的时间思考这个问题,终于找到了一种改变方法,如下所示:

protocol Serializable {} // Empty protocol

protocol AncestorListDataModel {
  func getGeneric(at index: Int) -> Serializable?
}

protocol ListDataModel: AncestorListDataModel {
  associatedtype T: Serializable
  var items: [T] { get }
}

extension ListDataModel {
  func getGeneric(at index: Int) -> Serializable? {
    if index >= 0 && index < items.count {
        return items[index]
    }

    return nil
  }
}

class BaseListDataModel<T>: ListDataModel where T: Serializable {
  ...
}

class BaseListDataSource: NSObject {
  private var listModels: [String: AncestorListDataModel] = [:]
  private(set) var modelMapping: [String: Serializable.Type] = [:]
  ...

  func getModel(of type: String, at index: Int) -> Serializable? {
    if let models = self.listModels[type] as? AncestorListDataModel {
        return models.getGeneric(at: index)
    }
    return nil
  }
}

在某个地方,我需要在ListDataModel中获取Person类型的元素

let dataSource = BaseListDataSource()
...

// Retrieve meta class type Person
if let personType = dataSource.modelMapping("Person") {
  // I want to get the first Person element in the Person list which I stored in dataSource
  let person = dataSource.getModel(of: String(describing: personType), at: 0) as! Person
}

我的想法是使用强制方法getGeneric(at:_)创建一个称为AncestorListDataModel的协议,该协议返回符合Serializable的实例,并且ListDataModel必须继承它。然后,我必须将此实例转换为要使用的类型。