Latest 1.1.0
License MIT
Platforms ios 10.0
Frameworks UIKit

CocoaPods Compatible

Using CellViewModel to configure you UITableViewCell or UICollectionViewCell is just a one possible approach of work with UIKit’s collections.


  • iOS 10.0+
  • Xcode 10.0+
  • Swift 4.2+



target 'MyApp' do
  pod 'CellViewModel', '~> 1.1'


github "AntonPoltoratskyi/CellViewModel" "master"


Works with UITableView & UICollectionView – one possible approach, inspired by CocoaHeads:

You can move configuration logic for UITableViewCell or UICollectionViewCell from -cellForRowAtIndexPath: to separate types.

1) You need to create cell class and appropriate type that conforms to CellViewModel type:

public typealias AnyViewCell = UIView

public protocol CellViewModel: AnyCellViewModel {
    associatedtype Cell: AnyViewCell
    func setup(cell: Cell)


import CellViewModel

// MARK: - View Model

struct UserCellModel: CellViewModel {
    var user: User

    func setup(cell: UserTableViewCell) {
        cell.nameLabel.text =

// MARK: - Cell

final class UserTableViewCell: UITableViewCell, XibInitializable {
    @IBOutlet weak var nameLabel: UILabel!

2) After that you need to register created model type:

There are 2 options:

  • use register(nibModel:) if appropriate CellViewModel‘s Cell conforms to XibInitializable:

    tableView.register(nibModel: UserCellModel.self)
  • otherwise use register(viewModel:):
    tableView.register(viewModel: UserCellModel.self)

3) Then store your models in array (or your custom datasource type):

private var users: [AnyCellViewModel] = []

AnyCellViewModel is a base protocol of CellViewModel.
It’s needed only in order to fix compiler limitation as you can use protocols with associatedtype only as generic constraints and can’t write something like this:

private var users: [CellViewModel] = [] // won't compile

4) UITableViewDataSource implementation is very easy, even if you have multiple cell types, because all logic are contained in our view models:

import CellViewModel

class ViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!

    private var users: [AnyCellViewModel] = []

    override func viewDidLoad() {
        users = { UserCellModel(user: $0) }
        tableView.register(nibModel: UserCellModel.self)

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return users.count

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withModel: tableModel(at: indexPath), for: indexPath)

    private func tableModel(at indexPath: IndexPath) -> AnyCellViewModel {
        return users[indexPath.row]

5) Or use TableViewDataAdapter:

private lazy var adapter = TableViewDataAdapter(tableView: self.tableView)

assign it as UITableView’s dataSource:

override func viewDidLoad() {
    self.tableView.dataSource = adapter

updating data property will cause reloadData()

func setup(users: [AnyCellViewModel]) { = users


Sometimes there is a need to define accessibilityIdentifier for UI testing purposes.

There is Accessible protocol that is conformed by CellViewModel protocol.

public protocol Accessible {
    var accessibilityIdentifier: String? { get }
    var accessibilityOptions: AccessibilityDisplayOptions { get }

So you need to define accessibilityIdentifier property in your model type implementation:

struct UserCellModel: CellViewModel {

    var accessibilityIdentifier: String? {
        return "user_cell"

    // ...

And define accessibilityOptions if needed to add index path as suffix in the end of accessibilityIdentifier:

struct UserCellModel: CellViewModel {

    var accessibilityIdentifier: String? {
        return "user_cell"

    var accessibilityOptions: AccessibilityDisplayOptions {
        return [.row, .section]

    // ...


CellViewModel is available under the MIT license. See the LICENSE file for more info.

Latest podspec

    "name": "CellViewModel",
    "version": "1.1.0",
    "summary": "CellViewModel is a protocol that includes logic for reuse, accessibility and dequeue",
    "description": "Using CellViewModel to configure you UITableViewCell or UICollectionViewCell is just a one possible approach of work with UIKit's collections.",
    "homepage": "",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    "authors": "Anton Poltoratskyi",
    "platforms": {
        "ios": "10.0"
    "source": {
        "git": "",
        "tag": "1.1.0"
    "source_files": [
    "frameworks": "UIKit",
    "swift_version": "4.2"

Pin It on Pinterest

Share This