首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >重拾swift版本MVP

重拾swift版本MVP

作者头像
大话swift
发布于 2019-07-04 11:21:20
发布于 2019-07-04 11:21:20
1.2K0
举报
文章被收录于专栏:大话swift大话swift

之前我们聊过MVP的,也简单写了个人采用swft版本MVP,今天我们结合实例进行简单优化实践……

talk is cheap ,show you code

代码语言:javascript
复制
public protocol IView {}
public protocol IPresenter {
    associatedtype View: IView
    var mView: View? {get}
    func bind(to view: View)
}

public protocol Contract {
     associatedtype Presenter: IPresenter
     associatedtype View: IView
    var presenter: Presenter? {get}
    func bind( _ view: View)
}

代码中我们定义了Presenter View 协议,然后让Contract进行统一管理。也许你会疑问为啥让Contract来处理?其实从字面意思就可以看出Contract有契约之意。也就是说咱们想使用就要遵循这个契约……

接下来我们来做一些基础性的事情:

到目前为止我们看到所有的都是不能实例化的协议。那么MVP我们从哪个开始入手呢?当然是主角P啦--MVP的模式就是将MVC中的C复杂逻辑主战场移动到了P中……而对于P来说势必会持有:View 和 负责对View的绑定,于是……下面的P的基类应运而生

代码语言:javascript
复制
public class BasePresenter<V>:NSObject, IPresenter where V: IView{
    public func bind(to view: View) {
        mView = view
    }
    public typealias View = V
  public  var mView: View?
    func getView()->V?{
        return mView
    }
}

BasePresenter作为IPresenter的基础逻辑扩充,同时负责从C中View的绑定,最终完成交互C=>P=>V=>C的一个完成闭环…

万事具备,下面我们看看怎么完成一个简单的MVP流程……在展示流程的时候我们先看看基本的项目结构

我们把Contract Presenter View分别单独出来,然后完成自己影有的逻辑……我们结合?按照View Presenter Contract的顺序来讲解

1 View

代码语言:javascript
复制
protocol MainMenuIView: IView {
    func onMainItemSelected(mainMenu: MainMenu)
}

extension MainMenuViewController:  MainMenuIView{
    func onMainItemSelected(mainMenu: MainMenu) {
        
    }
}

这个View很简单就是实现一个TableView点击的响应传递,此处我们将ViewController作为MVP中的View,而Controller只需要接受MVP传递的数据和事件完成UI的跳转控制即可----逻辑和事件数据交个MVP,而Controller只需要页面跳转穿插即可

2 Presenter

代码语言:javascript
复制

class MainMenuPresenter:  BasePresenter<MainMenuViewController>  {
    func onMainItemSelected(mainMenu: MainMenu){
        getView()?.onMainItemSelected(mainMenu: mainMenu)
    }
    override func bind(to view: MainMenuViewController) {
        super.bind(to: view)
        getView()?.mainMenuTableView.dataSource = self
        getView()?.mainMenuTableView.delegate = self
    }
}

extension MainMenuPresenter : NSTableViewDelegate {
    func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
        let tableViewCell:NSTableCellView  =   tableView.makeView(withIdentifier: NSUserInterfaceItemIdentifier.init("main_menu_cell"), owner: self) as! NSTableCellView
        
        tableViewCell.textField?.stringValue = "xxxxxxx"
        return tableViewCell
    }
    func tableView(_ tableView: NSTableView, dataCellFor tableColumn: NSTableColumn?, row: Int) -> NSCell? {
        return nil
    }
    func numberOfRows(in tableView: NSTableView) -> Int {
        return 3
    }
    
}
extension MainMenuPresenter : NSTableViewDataSource{
    func tableViewSelectionDidChange(_ notification: Notification) {
        
    }
    
}

Presenter比较复杂啦,除了需要对VIew进行绑定,同时需要对UI进行一些数据的初始化,负责View的交互和PV事件的传递…

例如此处:TableVIew的点击事件或调用Presenter的func onMainItemSelected(mainMenu: MainMenu)然后Presnter将事件传递给View的实例来完成事件与数据的传递

3 Contract

代码语言:javascript
复制
protocol MainMenuViewControllerContract: Contract where View == MainMenuViewController ,Presenter == MainMenuPresenter  {}


extension MainMenuViewController : MainMenuViewControllerContract{
    
    var presenter: MainMenuPresenter? {
        return self.mainPresenter
    }
    
    func bind(_ view: MainMenuViewController) {
        presenter?.bind(to: self)
        self.mainMenuTableView.delegate = presenter
        self.mainMenuTableView.dataSource = presenter
    }
    
}

Contract是MVP的灵魂契约,在这里简单的一行代码

代码语言:javascript
复制
protocol MainMenuViewControllerContract: Contract where View == MainMenuViewController ,Presenter == MainMenuPresenter  {}

我们让Presenter IView知道了各自的具体类型,然后将P V进行绑定穿插完成一个基本的MVP闭环……

最后让我们看看显示结果完成咱们今天的小实例

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-06-21,如有侵权请联系 cloudcommunity@tencent.com 删除
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档