связывание перечислимых случаев будет именем класса - PullRequest
0 голосов
/ 20 мая 2019

Описание

У меня есть перечисления с именами дел, которые соответствуют именам классов.Я использую перечисление для заполнения разделов / строк UITableView.Когда пользователь выбирает строку, я хотел бы создать экземпляр соответствующего класса и создать экземпляр объекта этого класса.

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

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

Дополнительный контекст

Я создал таблицу поиска для подключения "Секция "перечисляет дела в соответствующие им подробные перечисления:

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
    }
}

Я смотрю на это , но я могу 'Кажется, чтобы это сработало.Мое (небольшое) понимание проблемы - это безопасность типов 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. Много запаха кода.

Вопрос

Когда я пытаюсь понять это ответ , я вижу, что теперь можно было бы использоватьмои классы напрямую для заполнения UITableView.

Я не уверен, с чего начать с этого утверждения:

«Например, он должен предоставлять метод для заполнения NSView или ячейки таблицы.Таким образом, каждый класс может определить свой собственный тип пользовательского интерфейса, который будет представлен для его конкретных настраиваемых параметров… »

См. Скриншот UITableView

Ответы [ 2 ]

0 голосов
/ 20 мая 2019

Проблема: я не мог понять, как заполнить UITableView

Почему бы вам не создать прямой тип, представляющий иерархию строк-разделов?

Подготовьте некоторый протокол, представляющий строку:

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

И определите структуру, представляющую раздел:

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

С помощью этих выше вы можете объявить модель данныхваше табличное представление в виде массива 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: [
        //...
    ]),
    //...
]

0 голосов
/ 20 мая 2019

Такое переключение и принудительное приведение к одному из многих возможных типов - серьезный запах кода, указывающий на упущенную возможность применить объектно-ориентированное проектирование.

Мне кажется, вы бы очень выиграли от протокола DressCustomization, которому соответствуют ваши различные настройки.Затем создайте набор классов, соответствующих этому протоколу.Вам нужен один DressCustomization класс на «категорию» настроек.Под «категорией» я подразумеваю набор настроек, которые имеют общие настраиваемые параметры, варианты использования и пользовательский интерфейс.Например,

  • «ElongateCustomization» - это та, которая просто хранит название некоторой области платья и длину, на которую его можно удлинить
  • «ColorCustomization» - это та, котораяхранит название некоторой области платья и цвет, который будет использоваться для него
  • "AddOnCustomization" - это тот, который хранит название добавляемой функции

The *Протокол 1015 * - это унифицирующий протокол, который позволяет вам хранить / обрабатывать любую из этих настроек единообразным способом.Например, он должен предоставлять метод для заполнения NSView или ячейки таблицы.Таким образом, каждый класс может определять свой собственный тип пользовательского интерфейса для представления для своих конкретных настраиваемых параметров.Например, виды, представленные ElongateCustomization, представляют сборщик для секции платья и ввод числа для длины удлинения.Представления, представленные ColorCustomization, представляют собой средство выбора для секции одежды и цветовую палитру для ввода.

Эти DressCustomization объекты также являются частью вашей модели данных.Ваши различные ячейки таблицы могут хранить ссылки на них (для каждого класса DressCustomization у вас будет соответствующий подкласс UITableViewCell), и вы можете воздействовать на них напрямую.Приведение не требуется.

По сути, практически в любом случае, когда вы обнаруживаете, что переходите на одно из множества значений и делаете одну вещь из множества возможных, это является убедительным свидетельством того, что вы можете использовать полиморфизм.Таким образом, вы можете легко определить новые настройки, а не искать свою базу кода, добавляя в новые случаи переключения, принудительное приведение и другую подобную ерунду.

...