swift - 关联枚举案例将类名

标签 swift uitableview class enums

描述

我有枚举,其案例名称与类名称相对应。我使用枚举来填充 UITableView 的部分/行。当用户选择一行时,我想实例化相应的类并实例化该类的对象。

// example enum:
enum BodiceEnum: String, CaseIterable {
    case AddBraCups
    case AddOrRemoveBoning
    // other cases hidden
    }

// example classes:
class AddBraCups { // implementation hidden }
class AddOrRemoveBoning { // implementation hidden}

其他上下文

我制作了一个查找表来将“Section”枚举案例连接到其相应的详细枚举案例:

var alterationsLookupTable: [(String,[Any])] = [
    ("Bodice",BodiceEnum.allCases),
    ("Neckline",NecklineEnum.allCases),
    ("Sides",SidesEnum.allCases),
    ("Sleeves or Straps",SleevesOrStrapsEnum.allCases),
    ("Back of Dress",BackOfDressEnum.allCases),
    ("Seams",SeamsEnum.allCases),
    ("Hem",HemEnum.allCases),
    ("Skirt",SkirtEnum.allCases),
    ("Veils",VeilsEnum.allCases),
    ("Prom - Straps",PromStrapsEnum.allCases),
    ("Prom - Take in/out",PromTakeInOrOutEnum.allCases),
    ("Prom - Hem",PromHemEnum.allCases),
    ("Tux",TuxEnum.allCases),
]

当前 UITableView 部分对应于此 alterationsLookupTable 数组中的索引。

一旦获得正确的部分类型,我就会切换该部分的相应枚举情况。我正在切换 itemsTuple.0,然后使用当前的 indexPath.row 值作为 itemsTuple.1

中的索引
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
        //var alterationDetailsArray: [String]()
        let section = indexPath.section
        var cellText: String = ""
        let itemTuple = alterationsLookupTable[section]
        switch itemTuple.0 {
        case "Bodice":
            let items = itemTuple.1 as! [BodiceEnum]
            cellText = items[indexPath.row].readable
        case "Neckline":
             let items = itemTuple.1 as! [NecklineEnum]
            cellText = items[indexPath.row].readable
        case "Sides":
            let items = itemTuple.1 as! [SidesEnum]
            cellText = items[indexPath.row].readable
        case "Sleeves or Straps":
            let items = itemTuple.1 as! [SleevesOrStrapsEnum]
            cellText = items[indexPath.row].readable
        case "Back of Dress":
            let items = itemTuple.1 as! [BackOfDressEnum]
            cellText = items[indexPath.row].readable
        case "Seams":
            let items = itemTuple.1 as! [SeamsEnum]
            cellText = items[indexPath.row].readable
        case "Hem":
            let items = itemTuple.1 as! [HemEnum]
            cellText = items[indexPath.row].readable
        case "Skirt":
            let items = itemTuple.1 as! [SkirtEnum]
            cellText = items[indexPath.row].readable
        case "Veils":
            let items = itemTuple.1 as! [VeilsEnum]
            cellText = items[indexPath.row].readable
        case "Prom - Straps":
            let items = itemTuple.1 as! [PromStrapsEnum]
            cellText = items[indexPath.row].readable
        case "Prom - Take in/out":
            let items = itemTuple.1 as! [PromTakeInOrOutEnum]
            cellText = items[indexPath.row].readable
        case "Prom - Hem":
            let items = itemTuple.1 as! [PromHemEnum]
            cellText = items[indexPath.row].readable
        case "Tux":
            let items = itemTuple.1 as! [TuxEnum]
            cellText = items[indexPath.row].readable
        default:
            cellText = "not valid cell text"
            
        }
        cell.textLabel?.text = cellText
        return cell
    }
}

我一直在看this但我似乎无法让它发挥作用。我对这个问题的(一点点)了解是 Swift 的类型安全。我猜想有一种 Swifty(惯用的)方法可以实现这一点。

更新 2:

这是一个更改部分的示例 —> Hem 及其子类之一 —> AddHemLace

class Hem : Codable {
    var minCost: Float
    var maxCost: Float
    var actualCost: Float

    var name: String {
        let thisType = type(of: self)
        return String(describing: thisType)
    }

    init(minCost: Float, maxCost: Float, actualCost: Float) {
        self.minCost = minCost
        self.maxCost = maxCost
        self.actualCost = actualCost
    }

    convenience init() {
        self.init(minCost: -1, maxCost: -1, actualCost: -1)
    }
}

class AddHemLace : Hem {
    var costDetails: String?
    var costUnit: String?
    var units: Int = 1
    var secondaryCost: Float = 0.0
    var secondaryCostDetails: String?

    var totalCost : Float {
        return self.actualCost * Float(self.units) + self.secondaryCost
    }

    init() {
        let min: Float = 50.00
        let max: Float = 80.00
        let actual: Float = min
        super.init(minCost: min, maxCost: max, actualCost: actual)
    }

    required init(from decoder: Decoder) throws {
        fatalError("init(from:) has not been implemented")
    }
}

问题:我不知道如何填充 UITableView

我制作了与我的类具有并行结构的相关枚举。

enum AlterationSectionsEnum: String, CaseIterable  {   
    case Hem
    // other cases
}

enum HemEnum: String, CaseIterable {
    case cutAndReplaceHem
    // other cases
}

然后我使用了一个大的 switch 语句、一个查找表和一些字符串解析 foo 来填充 UITableView。 Lots of code smell.

问题

当我试图理解这一点时 answer ,我现在看到可以直接使用我的类来填充 UITableView。

我不知道从哪里开始这个声明:

“例如,它应该提供一种方法来填充 NSView 或表格单元格。这样,每个类都可以定义自己的 UI 类型来呈现其特定的可配置参数......”

See screenshot of UITableView

最佳答案

问题:我不知道如何填充 UITableView

为什么不创建一个直接类型来表示节行层次结构?

准备一些代表一行的协议(protocol):

protocol AlterationType {
    var name: String {get}
    //... other common properties or methods
}

并定义一个代表节的结构:

struct AlterationSection {
    var sectionName: String
    var alterations: [AlterationType]
}

通过上述内容,您可以将 TableView 的数据模型声明为 AlterationSection 数组:

var alterationSections: [AlterationSection] = [
    //...
]

使用这个数组,您可以将 tableView(_:cellForRowAt:) 简单地编写为:

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //### `dequeueReusableCell(withIdentifier:)` may return nil,
        //### You should better use `dequeueReusableCell(withIdentifier:for:)` instead.
        //### (You need to register the identifier "Cell" in any of the available ways.)
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        let alterationSection = alterationSections[indexPath.section]
        cell.textLabel?.text = alterationSection.alterations[indexPath.row].name
        return cell
    }

您可以将 alterationSections 初始化为:

class Hem : Codable, AlterationType { //<-Add conformance to `AlterationType`
    //...
}

class AddHemLace : Hem {
    //...
}
var alterationSections: [AlterationSection] = [
    AlterationSection(sectionName: "Hem", alterations: [
        AddHemLace(),
        //...
    ]),
    AlterationSection(sectionName: "...", alterations: [
        //...
    ]),
    //...
]

关于swift - 关联枚举案例将类名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56212668/

相关文章:

ios - 将 UIButton 对齐到 UITableViewCell 的右侧

php - 从 javascript OOP 背景理解 php 类结构(如何调整代码工作流程)

ios - AVAudioSession 更改类别卡住 AVCapture 屏幕

ios - Swift 4 TableView 获取错误的单元格

swift - 有没有办法在 Swift 或 RxAlamofire 中退出浏览器 session ?

ios - 重置自定义表格单元格中所有 UITextfield 的值

java - java类中的类?

ruby - 是否可以为子模块赋予与顶级类相同的名称?

ios - 从外部项目目录读取 plist 文件

ios - 使用自动单元格高度配置 TableView 会导致不显示任何单元格