iOS开发:如何修改UITableViewCell实现ViewModel赋值?该写法是否规范?
cell.viewModel = articleVM a Best Practice? Absolutely! Using a dedicated viewModel property on your UITableViewCell is absolutely a best practice—and it’s even more valuable as your cell’s data requirements grow beyond just two labels. Here’s why this approach shines:
- Separation of Concerns: Your cell’s only job is to display data, not fetch or transform it. The
ArticleViewModelalready handles all the data formatting (like providing fallback "null" values), so your cell stays focused on UI. - Cleaner, More Maintainable Code: Instead of writing multiple lines of
label.text = ...incellForRowAt, you can set everything with a single line. If you later add more UI elements (like a Chinese content label), you only update the cell’sviewModelsetter—no changes needed in your view controller. - Reusability: If you use this cell in multiple places across your app, you don’t have to duplicate the data-assignment logic everywhere. Just pass the view model, and the cell handles the rest.
cell.viewModel = articleVM Let’s adjust your ArticleTalbeViewCell (note: you have a typo here—should be ArticleTableViewCell!) to support this pattern:
Step 1: Add a ViewModel Property to the Cell
Update your cell class to include a viewModel property with a didSet observer that triggers UI updates:
class ArticleTalbeViewCell: UITableViewCell { // Optional: Make these non-optional (safer, since we initialize them in setupUI) let titlelabel = UILabel() let descriptionLabel = UILabel() // Add the viewModel property here var viewModel: ArticleViewModel? { didSet { updateUI() } } 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() { titlelabel.numberOfLines = 0 descriptionLabel.numberOfLines = 0 descriptionLabel.textColor = UIColor.lightGray descriptionLabel.setContentHuggingPriority(UILayoutPriority.defaultHigh, for: .vertical) let staview = UIStackView() staview.axis = .vertical staview.addArrangedSubview(titlelabel) staview.addArrangedSubview(descriptionLabel) staview.spacing = 8 staview.translatesAutoresizingMaskIntoConstraints = false self.contentView.addSubview(staview) NSLayoutConstraint.activate([ staview.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 5), staview.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -5), staview.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 5), staview.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -5) ]) } // Add this method to update UI when the viewModel changes private func updateUI() { guard let viewModel = viewModel else { // Reset UI if viewModel is nil (good for cell reuse) titlelabel.text = nil descriptionLabel.text = nil return } titlelabel.text = viewModel.title descriptionLabel.text = viewModel.description // If you later need to show the `chines` field: // chinesLabel.text = viewModel.chines } }
Step 2: Update Your View Controller’s cellForRowAt
Now you can simplify your data assignment to a single line:
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 // That's it! return cell }
Optional: Add the chines Property to ArticleViewModel
If you want to display the chines field later, just add it to your view model:
extension ArticleViewModel { var chines: String { return self.article.chines ?? "null" } }
Then add a chinesLabel to your cell and update the updateUI() method—no changes needed in your view controller!
内容的提问来源于stack exchange,提问作者jiexishede

