abagmut
abagmut

Reputation: 911

Generic MVP implementation in Swift

The idea is to implement MVP structure with base protocols and classes which hold reference to generic view and presenter

// --- Base --- //
protocol BaseViewProtocol: class {
    associatedtype P: BasePresenterProtocol
    var presenter: P? { get set }
}
class BaseView<P: BasePresenterProtocol>: UIView, BaseViewProtocol {
    var presenter: P?
}

protocol BasePresenterProtocol {
    associatedtype V: BaseViewProtocol
    weak var view: V? { get set }
}
class BasePresenter<V: BaseViewProtocol>: BasePresenterProtocol {
    weak var view: V?
}

// --- Current --- //
protocol CurrentViewProtocol: BaseViewProtocol {
}
class CurrentView<P: CurrentPresenterProtocol>: BaseView<P>, CurrentViewProtocol {
}

protocol CurrentPresenterProtocol: BasePresenterProtocol {
}
class CurrentPresenter<V: CurrentViewProtocol>: BasePresenter<V>, CurrentPresenterProtocol {
    init(currentView: V) {
        super.init()
        self.view = currentView
    }
}

The question is how to instantiate concrete implementation of all these classes, since both View and Presenter are generic classes and depend on each other

Upvotes: 0

Views: 693

Answers (1)

SuryaKantSharma
SuryaKantSharma

Reputation: 1183

Not sure this is best way but i had done similar thing in this way

  protocol Presentable {
  associatedtype View: ViewAble
  weak var view: View? {get set}

  init(with view: View)

  func onAttach(view: View)
  func onDetach()

   var isAttached: Bool {get}
}

extension Presentable {
  var isAttached: Bool {
    return view != nil
  }
}



class Presenter: Presentable {

 weak var view: ViewAble? {
    didSet {
      if let view = view {
        onAttach(view: view)
      } else {
        onDetach()
      }
    }
  }


  required init(with view: ViewAble) {
    self.view = view
  }

  func onAttach(view: View) {
    //pre set up on construction

  }
  func onDetach() {
    //release some resource on destroying view
  }
}




@objc protocol ViewAble: class {
  @objc optional func showError(_ message: String, _ callBack: (() -> Void)?)
}

extension ViewAble where Self: UIViewController {
  func showAlert(_ message: String?, _ callBack: (() -> Void)? = nil) {
    let alertController = UIAlertController(title: nil, message: message, preferredStyle: .alert)
    alertController.addAction(UIAlertAction(title: "OK", style: .default) { action in
      callBack?()
    })
    self.present(alertController, animated: true, completion: callBack)
  }

  func showLoading() {
    //show default Loading here and override if want custom

  }
  func stopLoading() {
    //stop default Loading
  }
}

class ViewController: ViewAble {

 }

Upvotes: 1

Related Questions