iOS -Swift Dynami c Использование UIViewController с несколькими настраиваемыми типами атрибутов - PullRequest
1 голос
/ 25 мая 2020

Итак, у меня есть ViewController с атрибутом типа «Something», этот же контроллер представления, который я хочу использовать с другим атрибутом типа «something1», я думал о создании протокола для каждого настраиваемого типа «something» "и" something1 ", и они доставляют то, что мне нужно, внутри ViewController, но оба являются структурами, и они не будут работать, поскольку оба являются типами значений.

мой примерный код следующий:

final class DynamicViewController: UIViewController {

private let attribute: CustomType // something or Somthing1
private let stackView: UIStackView

init(attribute: CustomType) {
    self.attribute = attribute
    super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    setupViews()
}

private func setupViews() {
    let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)

    NSLayoutConstraint.activate ([
        ...
    ])

    scrollView.addSubview(stackView)

    NSLayoutConstraint.activate([
    ...
    ])

    getInfoLabels()
}

private func getInfoLabels() {
    if let attribute = attribute {
        numerateInObjectAndGetLabel(obj: attribute)
    }
}

private func numerateInObjectAndGetLabel(obj: Any) {
    let mirroredAttr = Mirror(reflecting: obj)
    for (_, attr) in mirroredAttr.children.enumerated() {
        if let txts = attr.value as? [String] {
            for txt in txts {
                stackView.addArrangedSubview(getLabel(for: txt))
            }
        }
    }
}

private func getLabel(for text: String) -> UILabel {
    let label = UILabel()
    ....
    return label
}}

У меня есть решение сделать несколько дополнительных атрибутов с несколькими настраиваемыми типами, но в моем случае у меня более 10 настраиваемых типов, поэтому он будет некрасивым.

Есть ли способ решить эту проблему с помощью аккуратный и чистый подход? Мне очень не нравится избыточный код.

Ответы [ 2 ]

0 голосов
/ 25 мая 2020

Итак, в качестве решения я создал протокол и определил его внутри структуры, но мне пришлось сделать структуру не кодируемой, поскольку в моем случае это не проблема, если это проблема, вы можете использовать init (from :) и с ключами кодирования.

затем я заставил свой DynamicViewController расширить этот протокол, конечно, мне нужно было установить делегат структуры (протокол) для контроллера представления.

ответ:

let dynamicViewController = DynamicViewController()
    something.delegate = dynamicViewController
    navigationController?.pushViewController(abuseOverdosageViewController, animated: true)

------------------------------------------------------------

final class DynamicViewController: UIViewController, CustomProtocol {

private let stackView: UIStackView

init(attribute: CustomType) {
    self.attribute = attribute
    super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

override func viewDidLoad() {
    super.viewDidLoad()
    setupViews()
}

private func setupViews() {
    let scrollView = UIScrollView()
    scrollView.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(scrollView)

    NSLayoutConstraint.activate ([
        ...
        ])

    scrollView.addSubview(stackView)

    NSLayoutConstraint.activate([
        ...
        ])
}

/// PROTOCOL
func getView(view: UIView) {
    stackView.addArrangedSubview(view)
   }
}
-------------------------------------------


protocol CustomProtocol {
   func getView(view: UIView)
}


-------------------------------------------
struct Something {

public var delegate: CustomProtocol? {
    didSet {
        numerateInObjectAndGetLabel(obj: self)
    }
}

/// attributes
public var ......
public var .....
public var ....
public var ...
public var ..


private func numerateInObjectAndGetLabel(obj: Any) {
    let mirroredAttr = Mirror(reflecting: obj)
    for (_, attr) in mirroredAttr.children.enumerated() {
        if let txts = attr.value as? [String] {
            for txt in txts {
                delegate?.getView(view: getLabel(for: txt))
            }
        }
    }
}

private func getLabel(for text: String) -> UILabel {
    let label = UILabel()
    ...
    return label
   }
}
0 голосов
/ 25 мая 2020

Я думаю, что лучше всего изменить «атрибут» переменной на протокол, а затем использовать классы, реализующие этот протокол.

Кстати:

final class DynamicView: UIViewController

Вы должны переименовать его на:

DynamicViewController

, потому что это тип UIViewController, а не UIView.

...