Skip to content

Instantly share code, notes, and snippets.

@zhouhao27
Created February 18, 2020 07:33
Show Gist options
  • Save zhouhao27/86d46b59a077535fdb763c559ca79b2d to your computer and use it in GitHub Desktop.
Save zhouhao27/86d46b59a077535fdb763c559ca79b2d to your computer and use it in GitHub Desktop.
A MVP demo
//: A UIKit based Playground for presenting user interface
import UIKit
import PlaygroundSupport
struct User {
let firstName: String
let lastName: String
let email: String
let age: Int
}
class UserService {
//the service delivers mocked data with a delay
func getUsers(callBack:@escaping ([User]) -> Void) {
let users = [User(firstName: "Iyad", lastName: "Agha", email: "iyad@test.com", age: 36),
User(firstName: "Mila", lastName: "Haward", email: "mila@test.com", age: 24),
User(firstName: "Mark", lastName: "Astun", email: "mark@test.com", age: 39)
]
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 2) {
callBack(users)
}
}
}
// data passed to view because view doesn't need to know the model itself
struct UserViewData {
let name: String
let age: String
}
protocol UserView: class {
func startLoading()
func finishLoading()
func setUsers(users: [UserViewData])
}
class UserPresenter {
private let userService:UserService
weak private var userView : UserView?
init(userService:UserService){
self.userService = userService
}
func attachView(view:UserView){
userView = view
}
func detachView() {
userView = nil
}
func getUsers(){
print("getUsers")
self.userView?.startLoading()
userService.getUsers{ [weak self] users in
self?.userView?.finishLoading()
if(users.count == 0){
self?.userView?.setUsers(users:[])
}else{
let mappedUsers = users.map {
return UserViewData(name: "\($0.firstName) \($0.lastName)", age: "\($0.age) years")
}
self?.userView?.setUsers(users: mappedUsers)
}
}
}
}
class MyViewController : UIViewController {
var emptyView: UIView?
var tableView: UITableView?
var activityIndicator: UIActivityIndicatorView? // TODO: To be implemented
private weak var userPresenter: UserPresenter!
private var usersToDisplay = [UserViewData]() // covert from model to ViewModel
init(presenter: UserPresenter) {
super.init(nibName: nil, bundle: nil)
self.userPresenter = presenter
self.userPresenter.attachView(view: self)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
print("loadView")
view = UIView()
view.backgroundColor = UIColor.white
setupEmptyView()
setupTableView()
}
override func viewDidLoad() {
super.viewDidLoad()
print("viewDidLoad")
setupIndicator()
self.userPresenter.getUsers()
}
private func setupEmptyView() {
emptyView = UIView()
emptyView!.backgroundColor = .yellow
view.addSubview(emptyView!)
setupConstraints(for: emptyView!)
}
private func setupTableView() {
tableView = UITableView()
view.addSubview(tableView!)
setupConstraints(for: tableView!)
tableView?.delegate = self
tableView?.dataSource = self
tableView?.register(UITableViewCell.self, forCellReuseIdentifier: "UserCell")
}
private func setupIndicator() {
activityIndicator = UIActivityIndicatorView(style: UIActivityIndicatorView.Style.gray)
activityIndicator!.hidesWhenStopped = true
view.addSubview(activityIndicator!)
activityIndicator!.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
activityIndicator!.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
activityIndicator!.centerYAnchor.constraint(equalTo: self.view.centerYAnchor)
])
}
private func setupConstraints(for view: UIView) {
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0),
view.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0),
view.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0),
view.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0),
])
}
}
extension MyViewController: UserView {
func startLoading() {
activityIndicator?.startAnimating()
}
func finishLoading() {
activityIndicator?.stopAnimating()
}
func setUsers(users: [UserViewData]) {
if users.isEmpty {
self.emptyView?.isHidden = false
self.tableView?.isHidden = true
} else {
self.emptyView?.isHidden = true
self.tableView?.isHidden = false
usersToDisplay = users
tableView?.reloadData()
}
}
}
extension MyViewController: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return usersToDisplay.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: UITableViewCell.CellStyle.subtitle, reuseIdentifier: "UserCell")
let userViewData = usersToDisplay[indexPath.row]
cell.textLabel?.text = userViewData.name
cell.detailTextLabel?.text = userViewData.age
cell.textLabel
return cell
}
}
// Present the view controller in the Live View window
let presenter = UserPresenter(userService: UserService())
let vc = MyViewController(presenter: presenter)
PlaygroundPage.current.liveView = vc
//PlaygroundPage.current.needsIndefiniteExecution = true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment