基于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
}
我们希望这样做,以便从我们从JSON响应中获得的字符串设置类型T.
//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)
我得到的只是错误:
有没有办法通过字符串来实现这一点,或者我是否真的需要为我从JSON响应中获得的任何类型创建一个巨大的“if-else”结构?
编辑: 我尝试使用Cell类型的参数向CellConfigurator添加一个init,这样它就可以从它自己的参数中推断出Type。
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)
我得到的错误是不能感染细胞类型。如果我尝试在&lt;&gt;中使用cellClass
例如:MyTypeTest<cellType>(viewModel: 3.76)
所有它给我的是“cellClass”没有声明。在我看来,我正在走向死胡同,在这种情况下,PAT无法以任何我能看到的方式推断出来。我发现这种限制非常令人难过。
答案 0 :(得分:1)
如果将结果从NSClassFromString
向下转换为可以调用已知初始化程序的类型,则可以执行此操作。如果它总是Toaster
或子类,那么你可以这样做:
if let myTypeOBJ = NSClassFromString("Toaster") as? Toaster.Type {
let test = myTypeTest(someOBJ: myTypeOBJ.init())
// test.someThing will be of type Toaster
}
为了使NSClassFromString
起作用,您还需要指定您希望如何在objc中表示类型名称,否则将在类型名称前面添加一些其他内容:
@objc(Toaster)
class Toaster: NSObject