【问题标题】:Swift different types of generics in arraySwift 数组中不同类型的泛型
【发布时间】:2018-12-25 19:51:34
【问题描述】:

所以我正在为 UITableView 创建一些视图模型。表格有不同的单元格类型,所以我使用了泛型,但是将它们放入数组时出现了一些问题。

首先我定义了一个结构:

private struct Section<E, C> where C: UITableViewCell {
    let cell: C.Type
    let rows: [E]
    let configure: (_ row: E, _ cell: inout C, _ index: Int) -> Void
}

然后我声明了一个数组:

private lazy var sections: [Any] = [
    Section(cell: TextFieldTableViewCell.self,
            rows: [
              TableRow(image: R.image.home.device.settings.name(),
                       title: R.string.localizable.deviceSettingsViewControllerElementDeviceName(),
                       content: device.name,
                       action: { _ in

              }),
              TableRow(image: R.image.home.device.settings.location(),
                       title: R.string.localizable.deviceSettingsViewControllerElementDeviceLocation(),
                       content: device.location,
                       action: { _ in

              })],
            configure: { row, cell, index in
    }),
    Section(cell: DeviceSettingsNightVisionTableViewCell.self,
            rows: [
              TableRow(image: R.image.home.device.settings.nightVision(),
                       title: R.string.localizable.deviceSettingsViewControllerElementNightVision(),
                       content: 0,
                       action: { _ in
              })],
            configure: { row, cell, index in
    })
  ]

问题是:

  1. 我无法指定数组的类型,因为它们实际上是不同的泛型。
  2. 如果我使用[Any]作为数组的类型,那么我每次取一个元素,都要转换成对应的类型,这和我原来的设计不符。
  3. 我做了一些搜索,意识到我可能需要使用协议来解决问题,但我尝试了很多次都失败了。

我期望的结果是,当我取一个元素时,我可以正确地得到它的类型而无需转换。

我目前的做法是这样的:

numberOfRowsInSection:

switch section {
        case 0:
          return (self.sections[section] as! Section<TableRow, TextFieldTableViewCell>).rows.count
        case 1:
          return (self.sections[section] as! Section<TableRow, DeviceSettingsNightVisionTableViewCell>).rows.count
        default:
          return 0
        }

显然不够优雅,请问有没有更好的解决方案,任何帮助或建议都非常感谢。

【问题讨论】:

    标签: ios arrays swift generics


    【解决方案1】:

    您可以为行对象使用协议,并使用标识符而不是类型,我不完全确定这会完全解决您的问题,但您可以尝试一下:

    protocol CellProtocol where Self: UITableViewCell {
        func bind(_ object: RowProtocol)
    }
    
    protocol RowProtocol {
    
    }
    
    struct Row1: RowProtocol {
    
    }
    
    struct Row2: RowProtocol {
    
    }
    
    private struct Section {
        let cellIdentifier: String
        let rows: [RowProtocol]
        let configure: (_ row: RowProtocol, _ cell: inout UITableViewCell, _ index: Int) -> Void
    
    
    }
    
    private lazy var sections: [Section] = [
        Section(cellIdentifier: "cell1",
                rows: [Row1()],
                configure: { row, cell, index in
        }),
        Section(cellIdentifier: "cell2",
                rows: [Row2()],
                configure: { row, cell, index in
        })
    ]
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if let cell = tableView.dequeueReusableCell(withIdentifier: sections[indexPath.section].cellIdentifier, for: indexPath) as? CellProtocol {
            cell.bind(sections[indexPath.section].rows[indexPath.row])
        }
    }
    

    让你的自定义单元格类符合CellProtocol,然后在bind函数里面,尝试将RowProtocol转换成Row1Row2来获取它们的值。

    我也不确定你将如何在该部分对象中进行配置,感觉不对,我宁愿让单元类自己处理配置。

    【讨论】:

    • 感谢您的帮助,我意识到这个问题没有完美的解决方案。于是我改变主意,借用Section的设计。
    猜你喜欢
    • 1970-01-01
    • 2020-04-09
    • 2018-07-02
    • 1970-01-01
    • 2018-10-24
    • 2018-10-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多