Swift Возвращает enum в виде строки или int в зависимости от типа регистра - PullRequest
0 голосов
/ 01 июля 2018

Попытка вернуть вывод JSON с использованием библиотеки Ciftable Swift. Я установил структуру для захвата значения «по умолчанию» из моего JSON. Значение по умолчанию в настоящее время имеет два выходных типа данных, строку или int. Я пытаюсь вернуть строковое значение, если 'default' - строка, и значение int, если это int.

struct Settings: Codable {
   let configDefault: IntOrString
   let name: String?
}

enum IntOrString: Codable {
        case integer(Int)
        case string(String)

        init(from decoder: Decoder) throws {
            let container = try decoder.singleValueContainer()
            if let int = try? container.decode(Int.self) {
                self = .integer(int)
                return
            }
            if let string = try? container.decode(String.self) {
                self = .string(string)
                return
            }
            throw DecodingError.typeMismatch(IntOrString.self, DecodingError.Context(codingPath: decoder.codingPath, debugDescription: "Wrong type for Default"))
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.singleValueContainer()
            switch self {
            case .integer(let x):
                try container.encode(x)
            case .string(let x):
                try container.encode(x)
            }
        }
    }

Все это декодируется в значение defaultValueHolder

let defaultValueHolder = try JSONDecoder().decode(Settings.self, from: jsonString)

Используя библиотеку форм Eureka, я пытаюсь установить значение таблицы в качестве String или Int по умолчанию, возвращаемых из JSON.

form +++ Section ("Values")
    // dynamically generates rows
    for values in defaultValueHolder {
            form.last! <<< IntRow() {
                $0.tag = values.name
                $0.title = values.name
                $0.value = values.IntOrString
    }

Проблема заключается в том, что при попытке добавить значение в значение $ 0. Я не могу привести его к типу перечисления IntORString и должен возвращать либо int, либо строку, в зависимости от того, объявлено ли IntRow или TextRow.

1 Ответ

0 голосов
/ 01 июля 2018

На самом деле IntRow и TextRow строки будут принимать только тип, определенный для их ячеек , как показано ниже,

open class IntCell: _FieldCell<Int>, CellType 
open class TextCell: _FieldCell<String>, CellType

это причина, по которой вам нужно извлечь значение из вашего IntOrString перечисления type, чтобы присвоить соответствующему cell's row.


Если вы хотите иметь строку, которая принимает ваш тип (IntOrString), тогда вы должны согласовать свой новый тип с Equatable как eureka cell с типами допустимых значений, которые соответствуют Equatable. Что-то, как показано ниже,

enum IntOrString: Codable, Equatable

Затем вы должны добавить новый cell с create xib file, как отмечено, для создания вашего пользовательского view, показанного ниже,

enter image description here

А затем вы можете обновить IntOrStringTableViewCell, как показано ниже,

import UIKit
import Eureka

class IntOrStringTableViewCell: Cell<IntOrString>, CellType {

    @IBOutlet private weak var valueLabel: UILabel!

    override func setup() {
        super.setup()
        self.updateValue()
    }

    override func update() {
        super.update()
        self.updateValue()
    }

    private func updateValue() {
        guard let value = self.row.value else { return }
        if case .integer(let int) = value {
            self.valueLabel.text = "\(int)"
        } else if case .string(let string) = value {
            self.valueLabel.text = string
        }
    }
}

final class IntOrStringRow: Row<IntOrStringTableViewCell>, RowType {

    required init(tag: String?) {
        super.init(tag: tag)

        self.cellProvider = CellProvider<IntOrStringTableViewCell>(nibName: "IntOrStringTableViewCell", bundle: Bundle.main)
    }
}

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

form +++ Section ("Values")
    // dynamically generates rows
    for values in defaultValueHolder {
         form.last! <<< IntOrStringRow() {
            $0.tag = values.name
            $0.title = values.name
            $0.value = values.IntOrString
}
...