Protocol Oriented MVVM - Auckland iOS Meetup
-
Upload
natasha-murashev -
Category
Technology
-
view
1.269 -
download
2
Transcript of Protocol Oriented MVVM - Auckland iOS Meetup
P!MVVM@NATASHATHEROBOT
"Swift Is a Protocol-Oriented Programming Language"
— Dave Abrahams, Professor of Blowing-Your-Mind
UITableViewDelegate UITableViewDataSourceUITextFieldDelegateNSURLSessionDelegateCLLocationManagerDelegateMCSessionDelegate
!
!
!
!
Artsy Engineering: MVVM in Swift
MODELlet amount = 6729383.99
VIEWYour balance is $6,729,383.99
VIEWMODELstruct AccountViewModel { let displayBalance: String
init(model: BankAccount) { let formattedBalance = model.balance.currencyValue displayBalance = "Your balance is \(formattedBalance)" }}
VIEWCONTROLLERvar viewModel = ViewModel(model: Account)
VIEWCONTROLLERvar viewModel = ViewModel(model: Account)
PROTOCOLS!!!
THE PROBLEMclass SwitchWithTextTableViewCell: UITableViewCell {
func configure( title: String, titleFont: UIFont, titleColor: UIColor, switchOn: Bool, switchColor: UIColor = .purpleColor(), onSwitchToggleHandler: onSwitchToggleHandlerType? = nil) { // configure views here }
}
PROTOCOLS TO THE RESCUE !
protocol SwitchWithTextCellProtocol { var title: String { get } var titleFont: UIFont { get } var titleColor: UIColor { get }
var switchOn: Bool { get } var switchColor: UIColor { get }
func onSwitchTogleOn(on: Bool)}
extension SwitchWithTextCellProtocol {
var switchColor: UIColor { return .purpleColor() }
}
class SwitchWithTextTableViewCell: UITableViewCell {
func configure(withDelegate delegate: SwitchWithTextCellProtocol) { // configure views here }
}
struct MinionModeViewModel: SwitchWithTextCellProtocol { var title = "Minion Mode!!!" var switchOn = true
var switchColor: UIColor { return .yellowColor() }
func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } }}
CELLFORROWATINDEXPATH// YourViewController.swiftlet cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell
// this is where the magic happens!cell.configure(withDelegate: MinionModeViewModel())
return cell
!
✍
protocol SwitchWithTextCellDataSource { var title: String { get } var switchOn: Bool { get }}
protocol SwitchWithTextCellDelegate { func onSwitchTogleOn(on: Bool)
var switchColor: UIColor { get } var textColor: UIColor { get } var font: UIFont { get }}
// SwitchWithTextTableViewCell
func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) { // configure views here }
struct MinionModeViewModel: SwitchWithTextCellDataSource { var title = "Minion Mode!!!" var switchOn = true}
extension MinionModeViewModel: SwitchWithTextCellDelegate {
var switchColor: UIColor { return .yellowColor() }
func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } }}
// SettingsViewController
let viewModel = MinionModeViewModel()cell.configure(withDataSource: viewModel, delegate: viewModel)return cell
!
@MHOLLEMANS: MIXINS AND TRAITS IN SWIFT 2.0
class AIPlayer: GameObject, AITrait, GunTrait, RenderTrait, HealthTrait { ...}
class ZapMonster: GameObject, GunTrait, RenderTrait, HealthTrait, MovementTrait { ...}
! "
protocol TextPresentable { var text: String { get } var textColor: UIColor { get } var font: UIFont { get }}
protocol SwitchPresentable { var switchOn: Bool { get } var switchColor: UIColor { get }
func onSwitchTogleOn(on: Bool)}
protocol ImagePresentable { var imageName: String { get }}
protocol TextFieldPresentable { var placeholder: String { get } var text: String { get }
func onTextFieldDidEndEditing(textField: UITextField)}
extension TextPresentable {
var textColor: UIColor { return .blackColor() }
var font: UIFont { return .systemFontOfSize(17) }}
!!!class SwitchWithTextTableViewCell: UITableViewCell {
func configure<T where T: TextPresentable, T: SwitchPresentable>(withPresenter presenter: T) // configure views here }}
!!!!!!typealias SwitchWithTextViewPresentable = protocol<TextPresentable, SwitchPresentable>
class SwitchWithTextTableViewCell: UITableViewCell {
func configure(withPresenter presenter: T) // configure views here }}
extension MinionModeViewModel: TextPresentable { var text: String { return "Minion Mode" } var textColor: UIColor { return .blackColor() } var font: UIFont { return .systemFontOfSize(17.0) }}
extension MinionModeViewModel: SwitchPresentable { var switchOn: Bool { return false } var switchColor: UIColor { return .yellowColor() }
func onSwitchTogleOn(on: Bool) { if on { print("The Minions are here to stay!") } else { print("The Minions went out to play!") } }}
let cell = tableView.dequeueReusableCellWithIdentifier("SwitchWithTextTableViewCell", forIndexPath: indexPath) as! SwitchWithTextTableViewCell
let viewModel = MinionModeViewModel()cell.configure(withPresenter: viewModel)return cell
!"#
"Change is the only constant."— Unknown
typealias SwitchWithTextViewPresentable = protocol<TextPresentable, SwitchPresentable, ImagePresentable>
class SwitchWithTextTableViewCell: UITableViewCell {
func configure(withPresenter presenter: T) // configure views here }}
extension MinionModeViewModel: ImagePresentable { var imageName: String { return "minionParty.png" }}
!"
> Use Protocols to Configure Your Views> Use Protocol Extensions for Defaults
> Use ViewModels to Provide Data for the Protocols
HOW CAN WE MAKE THIS BETTER?