【发布时间】:2018-03-16 19:49:02
【问题描述】:
编辑:(最初的例子太简单了,所以我重写了代码以更具体)
基于http://holko.pl/2016/01/05/typed-table-view-controller/
我正在尝试查看是否可以从字符串中设置类型的泛型参数..
假设我们有这个代码
protocol Updatable
{
associatedtype ViewModel
func updateWith(viewModel: ViewModel)
}
class ToasterCell: UITableViewCell
{
var toast: String?
func updateWith(viewModel: String) {
toast = viewModel
//Additional config...
}
}
extension ToasterCell: Updatable
{
typealias ViewModel = String
}
class PriceCell: UITableViewCell
{
var tagPrice: Float?
func updateWith(viewModel: Float) {
tagPrice = viewModel
//Additional config
}
}
extension PriceCell: Updatable
{
typealias ViewModel = Float
}
protocol CellConfiguratorType {
var reuseIdentifier: String { get }
var cellClass: AnyClass { get }
func updateCell(_ cell: UITableViewCell)
}
class MyTypeTest<Cell> where Cell: Updatable , Cell: UITableViewCell
{
let viewModel: Cell.ViewModel
let reuseIdentifier: String = String(describing: Cell.self)
let cellClass: AnyClass = Cell.self
init(viewModel: Cell.ViewModel) {
self.viewModel = viewModel
}
func updateCell(_ cell: UITableViewCell)
{
if let c = cell as? Cell
{
c.updateWith(viewModel: viewModel)
}
}
}
extension MyTypeTest: CellConfiguratorType{
}
let myTT1 = MyTypeTest<PriceCell>(viewModel: 3.76)
let myTT2 = MyTypeTest<ToasterCell>(viewModel: "Carpe Diem")
let data = [myTT1, myTT2] as [CellConfiguratorType] // data for the tableView
//register Cell calss ...
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cellConf = data[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: cellConf.reuseIdentifier)
cellConf.updateCell(cell)
return cell
}
我们希望它的类型 T 是从我们从 JSON 响应中获得的字符串中设置的。
//Some JSON {"list":[{"k":"Price","v":368.0},"{"k":"ToasterCell","v":"YOLO"},"{"k":"Toaster","v":"Space"},{"k":"PriceCell","v":1999}]}
JSON 值不直接映射到任何对象/类,所以我需要使用那个键“k”来知道要使用的女巫类。
我尝试使用“k”值中的字符串来设置单元配置器。
(简短示例)
//for now let skip any logic in decoding the value / viewModel.
let myTT1 = MyTypeTest<NSClassFromString(list.first.k + "Cell")>(viewModel: list.first.v as Any)
我得到的只是以下错误:
- 无法将类型“T”的值分配给类型“AnyClass”(又名“AnyObject.Type”)
- 使用未声明的类型“myTypeOBJ”
有没有办法通过字符串来做到这一点,还是我真的需要为我可以从我的 JSON 响应中获得的任何类型创建一个巨大的“if-else”结构?
编辑: 我尝试使用 Cell 类型的参数向 CellConfigurator 添加一个 init,以便它可以从它自己的参数推断类型。
init(viewModel: Cell.ViewModel, inferUsing: Cell){....}
我可以尝试在哪里使用它(但由于 PAT 妨碍了它,所以它不起作用)
func getSafeBundelName() -> String
{
if let namespace = Bundle.main.infoDictionary!["CFBundleExecutable"] as? String
{
return namespace
}
return ""
}
let cellClass = NSClassFromString("\(getSafeBundelName()).PriceCell") as? UITableViewCell.Type
let cell = cellClass?.init()
let myTT1 = MyTypeTest(viewModel: list.first.v as Any, inferUsing: cell)
我收到无法推断单元类型的错误。如果我尝试在 中使用 cellClass
例如:MyTypeTest<cellType>(viewModel: 3.76) 它给我的只是没有声明“cellClass”。在我看来,我正陷入死胡同,无法以任何我能看到的方式推断 PAT。我觉得这个限制非常非常可悲。
【问题讨论】: