2
\$\begingroup\$

I need to convert my model to fit data in tableview cell finding better approach

My Model

class MyResponseModel {
    var question: String = ""
    var id: String = ""
    var answer: String = ""
    //Other variables also but not required to display
     init(fromDictionary dictionary: [String:Any]) {
        self.question = (dictionary["question"] as? String) ?? ""
        self.id = (dictionary["id"] as? String) ?? ""
        self.answer = (dictionary["answer"] as? String) ?? ""
    }
    //MARK: Converting model to cell data
    func toModel() -> MyTblCellDetail {
        return MyTblCellDetail(title:self.question,detail:self.answer)
    }
}
//MARK: Initialize cell data with custom model
struct MyTblCellDetail {
    var title: String = ""
    var detail: String = ""
    var isSelected:Bool = false

    init(title:String,detail:String) {
        self.title = title
        self.detail = detail
    }
    init(data:MyResponseModel) {
        self.title = data.question
        self.detail = data.answer
    }
}

Note: I am reusing same cell to display most of the data so i will use the same method to converting all class model to MyTblCellDetail struct

So my question is which is better way to do the same or any other approach i can use for the same. Thank you!

\$\endgroup\$
3
  • \$\begingroup\$ I would consider replacing MyTblCellDetail entirely with a protocol. MyResponseModel then conforms to that protocol by providing computed properties called table, detail and isSelected. \$\endgroup\$ – Alexander Oct 9 '20 at 20:45
  • \$\begingroup\$ myResponsemodel is just for demo there are too many responses can you explain more \$\endgroup\$ – Jaydeep Vyas Oct 10 '20 at 11:45
  • \$\begingroup\$ Make a protocol, and make all of your models conform to it. docs.swift.org/swift-book/LanguageGuide/Protocols.html \$\endgroup\$ – Alexander Oct 10 '20 at 13:19
1
\$\begingroup\$

Here is suggestions. Every approach has pros/cons, depending your app architecture and model complexity.

class MyResponseModel {
  // I think values in response model should be let instead of var
  // By definition response model should be immutable
  let question: String
  let id: String
  let answer: String

  // I guess MyResponseModel will be initialized from JSON and you can just conform it to Codable
  // Then you don't need this init(from dictionary: [String: Any])
  init(from dictionary: [String: Any]) {
    self.question = (dictionary["question"] as? String) ?? ""
    self.id = (dictionary["id"] as? String) ?? ""
    self.answer = (dictionary["answer"] as? String) ?? ""
  }
}

struct MyTableCellViewModel {
  // I'm not sure what logic do you have, but I think it is better to define properties using let instead of var
  let title: String
  let detail: String
  let isSelected: Bool

  init(title: String, detail: String, isSelected: Bool) {
    self.title = title
    self.detail = detail
    self.isSelected = isSelected
  }

  // Approach #1: create initializer from necessary response model
  init(responseModel: MyResponseModel, isSelected: Bool) {
    self.init(title: responseModel.question, detail: responseModel.answer, isSelected: isSelected)
  }
}

// Approach #2: create separate mapper class (useful when you need to have external dependencies in order to map
// For example you need to add some info that is not relevant to MyResponseModel.
// Let's take cell selection info as an example

protocol MyTableCellSelectionProvider {
  func isCellSelected(for responseModel: MyResponseModel) -> Bool
}

struct MyTableCellViewModelMapper {
  let cellSelectionProvider: MyTableCellSelectionProvider

  func map(responseModel: MyResponseModel) -> MyTableCellViewModel {
    return MyTableCellViewModel(
      title: responseModel.question,
      detail: responseModel.answer,
      isSelected: cellSelectionProvider.isCellSelected(for: responseModel)
    )
  }
}

// Approach #3: define cell view model protocol

protocol MyCellViewModel {
  var title: String { get }
  var detail: String { get }
}

extension MyResponseModel: MyCellViewModel {
  var title: String { return question }
  var detail: String { return answer }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.