博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
今天我才学会iOS的MVP写法
阅读量:7087 次
发布时间:2019-06-28

本文共 4382 字,大约阅读时间需要 14 分钟。

目前写 iOS 程序差不多整整两年了,期间断断续续写过 3 个 iOS 项目。之前写 android 的时候使用了 MVP 架构,但是写 iOS 的时候一直没有找到好的 MVP 实践,所以之前项目的所有代码都是堆在 ViewController 中。虽然使用了较多的注释和#MARK 使得代码不那么凌乱,但是动辄几百甚至上千行的 ViewController 还是让人很抓狂。

直到昨天我开始写下一个 iOS 项目的时候,开始之前又谷歌了一次“iOS MVP”,这次终于找到几篇文章,让我找到了一个简单易懂的 MVP 实践。:

以登陆页面为例。要实现一个最简单的登陆页面如下:

第一步,View

在之前的项目中,页面的 UI 代码都是写在 ViewController 中, 在本次实践中将 UI 代码抽离出来, 写在 LoginView.swift 中(只写了输入框和按钮):

import UIKitprotocol LoginViewDelegate: NSObjectProtocol {    func loginWith(username: String, password: String)}class LoginView: UIView {    var delegate: LoginViewDelegate?    let usernameTf = UITextField()    let passwordTf = UITextField()    let loginBtn = UIButton()    override init(frame: CGRect) {        super.init(frame: frame)        initView()    }    required init?(coder aDecoder: NSCoder) {        fatalError("init(coder:) has not been implemented")    }    convenience init() {        self.init(frame: CGRect.zero)        initView()    }    func initView() {        self.backgroundColor = UIColor.white        // 用户名输入框        self.addSubview(usernameTf)        usernameTf.borderStyle = .roundedRect        usernameTf.snp.makeConstraints { (make) in            make.centerX.equalToSuperview()            make.top.equalToSuperview().offset(270)            make.left.equalToSuperview().offset(40)            make.right.equalToSuperview().offset(-40)        }        // 密码输入框        self.addSubview(passwordTf)        passwordTf.borderStyle = .roundedRect        passwordTf.snp.makeConstraints { (make) in            make.centerX.equalToSuperview()            make.top.equalTo(usernameTf.snp.bottom).offset(16)            make.left.equalToSuperview().offset(40)            make.right.equalToSuperview().offset(-40)        }        //登录按钮        Views.resetButton(loginBtn, title: "登录", color: UIColor.green, font: UIFont.systemFont(ofSize: 22))        self.addSubview(loginBtn)        loginBtn.addTarget(self, action: #selector(clickLoginButton), for: .touchUpInside)        loginBtn.snp.makeConstraints { (make) in            make.centerX.equalToSuperview()            make.top.equalTo(passwordTf.snp.bottom).offset(20)        }    }    @objc func clickLoginButton() {        delegate?.loginWith(username: usernameTf.text ?? "", password: passwordTf.text ?? "")    }}复制代码

如此只要在 ViewController 中实现 LoginViewDelegate 协议就可以捕获到登录按钮点击事件。

第二步,Presenter

presenter 有以下特点:

  • 处理用户交互的逻辑
  • 与 Model 层进行通信,将数据转换为 UI 友好的格式,并更新视图
  • 不依赖 UIKit

在这个例子中,presenter 只有一个执行登录请求的方法:

import Foundationstruct LoginSelfData {    let username: String    let password: String}protocol LoginSelf: NSObjectProtocol {    func startLoading()    func finishLoading()    func loginSucceed()    func loginFail(mes: String)    func noNetwork()}class LoginPresenter {    var loginSelf: LoginSelf?    /// 登录请求,点击登录按钮时调用    ///    /// - Parameters:    ///   - username: 用户名    ///   - password: 密码    func loginWith(username: String, password: String) {        let parameter = ["username": username, "password": password]        ...        // 执行登录请求        loginSelf?.startLoading()        ...        // 接收到返回数据        loginSelf?.finishLoading()        ...        // 登录成功        loginSelf?.loginSucceed()        ...        // 登录失败        loginSelf?.loginFail(mes: "msg")    }}复制代码

如此只要在 ViewController 中实现 LoginSelf 协议,就可以捕获到登录请求完成后的回调方法,这时就可以根据不同的回调方法更新视图。

第三步,ViewController

ViewController 中的代码很简单, 只要分别初始化 View 和 Presenter 并实现各自的协议就好。

import UIKitclass LoginViewController: UIViewController {    let loginPresenter = LoginPresenter()    var loginView: LoginView?    override func viewDidLoad() {        super.viewDidLoad()        loginPresenter.loginSelf = self        loginView = LoginView.init(frame: self.view.bounds)        loginView?.delegate = self        self.view = loginView    }}// MARK: - 更新视图extension LoginViewController: LoginSelf {    func startLoading() {    }    func finishLoading() {    }    func loginSucceed() {    }    func loginFail(mes: String) {    }    func noNetwork() {    }}// MARK: - 响应用户交互操作extension LoginViewController: LoginViewDelegate {    /// 登录    ///    /// - Parameters:    ///   - username: 用户名    ///   - password: 密码    func loginWith(username: String, password: String) {        loginPresenter.loginWith(username: username, password: password)    }}复制代码

小结

如此 一个相对简单的 iOS MVP 实践就完成了,采取这样的写法之后顿时感觉代码一下子很清晰,可能总的代码量会多一点,但是单个文件肯定会比之前的胖 ViewController 少,不仅方便同事之间交流,也方便自己查找代码、 修改 bug。

转载地址:http://sggml.baihongyu.com/

你可能感兴趣的文章
判断当前运行的平台
查看>>
checkbox 多选框 :jquery之全选、全不选、反选
查看>>
触摸屏
查看>>
ADO.net的学习
查看>>
AIX 中 Paging Space 使用率过高的分析与解决
查看>>
webservice 测试窗体只能用于来自本地计算机的请求
查看>>
Java 中队列的使用
查看>>
再见 2014,你好 2015
查看>>
13 SELECT 以外的内容
查看>>
存储过程分页
查看>>
Mongodb启动命令mongod参数说明
查看>>
第6章 数组----遍历数组(使用二维数组输出一个3行4列且所有元素都是0的矩阵)...
查看>>
初中面谈招生网上招生报名系统
查看>>
Oracle Flashback Technologies (总)
查看>>
.NET平台开源项目速览(9)软件序列号生成组件SoftwareProtector介绍与使用
查看>>
干货:史上最实用逃顶绝招十二式!
查看>>
鸟哥Linux私房菜 基础学习篇读书笔记(10):Linux磁盘和文件系统管理(3)
查看>>
简述Session 、Cookie、cache 区别
查看>>
large-scale analysis of malware downloaders
查看>>
pyqt声音输入
查看>>