iOS MVP模式,Github代码在此
上次说到MVVM,这次说MVP
MVVM更多强调View和ViewModel的联系,MVP是把一部分的VC逻辑转移到Presenter
如图(图无VC,同理,并不是说VC省去了,只是没画…)
还是写个TableView,这次带网络请求,所以目标就是把网络请求的代码扔到Presenter里给我们的VC减减肥,
在Presenter里,还是和MVC一样的delegate思想,要求调用的VC遵循这个协议,并且封装了网络请求和其他的业务逻辑
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| protocol UserPresenterDelegate: AnyObject { func presentUsers(users: [User]) func presentAlert(title: String, message: String) }
typealias Presenter = UserPresenterDelegate & UIViewController
class UserPresenter { weak var delegate: UserPresenterDelegate? public func setViewDelegate(delegate: Presenter) { self.delegate = delegate } public func getUsers() { guard let url = URL(string: "https://jsonplaceholder.typicode.com/users") else { return } URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, error == nil else { return } do { let users = try JSONDecoder().decode([User].self, from: data) print(users) self?.delegate?.presentUsers(users: users) } catch { print(error) } }.resume() } }
|
Model里就是简单的解码json数据
1 2 3 4
| struct User: Codable { let name: String let email: String }
|
在VC里要遵循Presenter的协议,然后通过presenter请求数据,更新tableview,例子很简单,可以看到把网络请求的功能从VC挪走
后续需要扩展业务的话可以在PresenterDelegate里增加,然后在VC里回调
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
| class UserVC: UIViewController, UITableViewDelegate, UITableViewDataSource { let tableView: UITableView = { let tableView = UITableView() tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") return tableView }() private let presenter = UserPresenter() private var users: [User] = []
override func viewDidLoad() { super.viewDidLoad() title = "Users" presenter.delegate = self presenter.getUsers() view.addSubview(tableView) tableView.delegate = self tableView.dataSource = self } override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() tableView.frame = view.bounds } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) let user = self.users[indexPath.row] cell.textLabel?.text = "👾\(user.name) 📧\(user.email)" return cell } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { users.count } func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) } }
extension UserVC: UserPresenterDelegate { func presentUsers(users: [User]) { self.users = users DispatchQueue.main.async { self.tableView.reloadData() } } func presentAlert(title: String, message: String) { } }
|