FortechRomania/ios-mvp-clean-architecture

I have some questions

Hflydragon opened this issue · 2 comments

image
here only one type of cells in tableview,how can i set up some differert cells according to datas where from network,becasure this controller don't owner the datas

One way to do it is to create protocols for both your cell view models and your cells, and have specific implementations for each type if cell.

A gist of it could look like this

class BooksPresenter {
    var books: [BookCellViewModel]
}

protocol BookCellViewModel {
    var viewType: BookCellViewType { get }
}

enum BookCellViewType {
    case Type1
    case Type2
}

extension BookCellViewType {
    func reusableIdentifier() -> String {
        switch self {
        case .Type1:
            return "Type1ReusableIdentifier"
        case .Type2:
            return "Type2ReusableIdentifier"
        default:
            return ""
        }
    }
}

protocol BookTableViewCell {
    func configureWith(_ viewModel: BookCellViewModel)
}

With you cellForRow implementation looking like

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let viewModel = presenter.books[indexPath.row]
    
    let cell = tableView.dequeueReusableCell(withIdentifier: viewModel.viewType.reusableIdentifier()) as! BookTableViewCell
    
    cell.configureWith(viewModel)
    
    return cell as! UITableViewCell
}

As you can see there is a bit of casting involved, my Swift skills got a bit rusty in the past couple of years so probably there is a more idiomatic way to do it.

One way to do it is to create protocols for both your cell view models and your cells, and have specific implementations for each type if cell.

A gist of it could look like this

class BooksPresenter {
    var books: [BookCellViewModel]
}

protocol BookCellViewModel {
    var viewType: BookCellViewType { get }
}

enum BookCellViewType {
    case Type1
    case Type2
}

extension BookCellViewType {
    func reusableIdentifier() -> String {
        switch self {
        case .Type1:
            return "Type1ReusableIdentifier"
        case .Type2:
            return "Type2ReusableIdentifier"
        default:
            return ""
        }
    }
}

protocol BookTableViewCell {
    func configureWith(_ viewModel: BookCellViewModel)
}

With you cellForRow implementation looking like

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let viewModel = presenter.books[indexPath.row]
    
    let cell = tableView.dequeueReusableCell(withIdentifier: viewModel.viewType.reusableIdentifier()) as! BookTableViewCell
    
    cell.configureWith(viewModel)
    
    return cell as! UITableViewCell
}

As you can see there is a bit of casting involved, my Swift skills got a bit rusty in the past couple of years so probably there is a more idiomatic way to do it.

thank you ! your suggestion helps me resolve my problem