Как отправить данные модели в ячейку внутри? - PullRequest
0 голосов
/ 09 июня 2019

У меня следующий код для отображения данных в табличном представлении.

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? ArticleTalbeViewCell else {
        fatalError("ArticleTableViewCell not found")
    }

    let articleVM = self.articleListVM.articleAtIndex(indexPath.row)
//        cell.viewModel = articleVM
        cell.titlelabel?.text = articleVM.title
        cell.descriptionLabel?.text = articleVM.description
        return cell
    }
}

Теперь мой код с

cell.titlelabel?.text = articleVM.title
cell.descriptionLabel?.text = articleVM.description

хорошо работают.

Является ли cell.viewModel = articleVM хорошей практикой?

Представьте, что я должен установить дату для ячейки много раз? Этот подход cell.viewModel = articleVM спасет несколько строк.

Код UITableViewCell ниже:

class ArticleTalbeViewCell: UITableViewCell {

    var titlelabel:UILabel?
    var descriptionLabel:UILabel?

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.setupUI()

    }

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

    private func setupUI() -> () {
        let label1 = UILabel()
        label1.numberOfLines = 0
        let label2 = UILabel()
        label2.numberOfLines = 0
        label2.textColor = UIColor.lightGray
        label2.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: NSLayoutConstraint.Axis.vertical)

        titlelabel = label1
        descriptionLabel = label2
        let staview = UIStackView()
        staview.axis = .vertical

        staview.addArrangedSubview(label1)
        staview.addArrangedSubview(label2)
        staview.spacing = 8
        staview.translatesAutoresizingMaskIntoConstraints = false // !important
        self.contentView.addSubview(staview)

        staview.topAnchor.constraint(equalTo: self.contentView.topAnchor,constant: 5).isActive = true
        staview.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -5).isActive = true
        staview.leftAnchor.constraint(equalTo: self.contentView.leftAnchor, constant: 5).isActive = true
        staview.rightAnchor.constraint(equalTo: self.contentView.rightAnchor, constant: -5).isActive = true
    }
}

Код ArticleListViewModel ниже:

struct ArticleListViewModel {
    let articles:[Article]
}

extension ArticleListViewModel {

    var numbeOfSections: Int {
        return 1
    }

    func numOfRowsInSection(_ section: Int) -> Int {
        return self.articles.count
    }

    func articleAtIndex(_ index: Int) -> ArticleViewModel {
        let article = self.articles[index]
        return ArticleViewModel(article)
    }
}

struct ArticleViewModel {
    private let article: Article
}

extension ArticleViewModel {
    init(_ article: Article) {
        self.article = article
    }
}

extension ArticleViewModel {
    var title: String {
        return self.article.title ?? "null"
    }

    var description: String {
        return self.article.description ?? "null"
    }
}

Код ArticleList ниже:

import Foundation

struct ArticleList: Decodable {
    let articles: [Article]
}

struct Article: Decodable {
    let title: String?
    let description: String?
    let chines: String?
}

Как отредактировать код "ячейки" для реализации cell.viewModel = articleVM?

Ответы [ 2 ]

1 голос
/ 21 июня 2019

Прежде всего, я не думаю, что предоставление cell.viewModel = articleVM не меняет слишком много.Поскольку вы создали ArticleListViewModel и ArticleViewModel , было бы то же самое, если бы вы создали эти виртуальные машины для ячейки табличного представления.Тем не менее, я могу дать вам несколько советов, которые я использую при использовании подхода MVVM.Вы можете добавить новое свойство в ячейку табличного представления, а затем с помощью свойства обозревателя присвоить ему значение.

cell.article = articleVM

Следовательно, любой из методов cellForRowAt не будет слишком длинным, и он почти такой же, как и вашпросмотр модели в вашей ячейке.

private var titlelabel:UILabel?
private var descriptionLabel:UILabel?

var article: ArticleViewModel? {
    didSet {
        guard let article = article else { return }
        titlelabel?.text = article.title
        descriptionLabel?.text = article.description
    }
}

Насколько я понимаю, ваш второй вопрос - если у вас есть переменная даты, а метод форматирования внутри cellForRowAt занимает слишком много пробелов и выглядит некрасиво.Вот почему вам нужно сделать свою бизнес-логику внутри модели представления.Ваша ячейка табличного представления отвечает только за то, чтобы показать, что она не отформатирована.Надеюсь, вам это понятно.Если у вас есть какие-либо вопросы, вы можете задать.

0 голосов
/ 25 июня 2019

Вместо настройки метода cell in tableView(_:cellForRowAt:) вы должны сконфигурировать cell в самом ArticleTalbeViewCell, используя модель dataSource, т.е.

class ArticleTalbeViewCell: UITableViewCell {
    private var titlelabel: UILabel?
    private var descriptionLabel: UILabel?

    //rest of the code...

    func configure(with article: Article) {
        self.titlelabel?.text = article.title
        self.descriptionLabel?.text = article.description
    }
}

В приведенном выше коде,

1. Нет необходимости выставлять titlelabel и descriptionLabel за пределами class ArticleTalbeViewCell. Итак, отметьте их обоих private.

2. Вам просто нужно вызвать метод configure(with:) вместе с экземпляром Article.

Почему метод, а не свойство типа Article?

Нет необходимости сохранять объект модели внутри ArticleTalbeViewCell до тех пор, пока он не потребуется где-то еще после того, как cell настроен один раз.

В методе tableView(_:cellForRowAt:) вам нужно просто вызвать метод configure(with:) для вашего cell вместе с экземпляром article в данном конкретном indexPath.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? ArticleTalbeViewCell else {
        fatalError("ArticleTableViewCell not found")
    }

    let article = self.articleListVM.articleAtIndex(indexPath.row)
    cell.configure(with: article)
    return cell
}

Кроме того, я не думаю, что есть необходимость создавать отдельный ArticleViewModel. Это не делает ничего особенного. Это просто дополнительная оболочка на Article.

Вы можете просто вернуть Article тип из articleAtIndex(_:) метода в extension ArticleListViewModel, т.е.

func articleAtIndex(_ index: Int) -> Article {
    let article = self.articles[index]
    return article
}

Почему конфигурация в кастоме UITableViewCell?

Это потому, что ваш tableView может содержать несколько пользовательских UITableViewCells. Добавление конфигурации всех cell в tableView(_:cellForRowAt:) сделает код здоровенным и не сможет читать. Лучше, если конкретная конфигурация cell обрабатывается самим cell вместо ViewController.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...