Component-driven UIs - Mobile Era 2016

Preview:

Citation preview

@JOHNSUNDELL

BUILDING COMPONENT-DRIVEN UIS

John Sundell Lead iOS Developer, Spotify

! "

! "#

CocoaPods/Carthage

Fastlane

Swift

Protocol oriented programming

Model-View-ViewModel

Promises / Operations / Rx

UI

// MARK: - UITableViewDataSource func numberOfSections(in tableView: UITableView) -> Int { return 2 } func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 0 { return model.unreadMessages.count } return model.readMessages.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "message", for: indexPath) let message: Message if indexPath.section == 0 { message = model.unreadMessages[indexPath.row] } else { message = model.readMessages[indexPath.row] } cell.textLabel?.text = message.subject cell.detailTextLabel?.text = "From: \(message.sender)" return cell }

UITableViewDelegate

UITableViewDataSource

Caching

UIViewController subclass

JSON parsing

Integrate view controller with the rest of the app

Setup UITableView

Register UITableViewCell classUITableViewCell subclass

Handle network errors

Handle slow connections

OfflinePerform HTTP request

View Model

City Model

BACKEND

Render state

[ Image(“Tokyo”), Image(“Gothenburg”), Row(“Berlin”, “Germany”), Row(“Beijing”, “China”), Row(“Paris”, “France”), Row(“San Francisco”, “USA”), User(“Julia”), User(“Mathew”), User(“Caroline”), User(“David”), Row(“Athens”, “Greece”), Row(“Oslo”, “Norway”), Row(“Stockholm”, “Sweden”)

]

UI = fn(state)

1. SHARED DATA MODEL

struct Image { var url: URL }

struct City { var name: String var country: String }struct User {

var name: String var imageUrl: URL }

ComponentModel

ComponentModel

ComponentModel

ViewModel

struct { var title: String var subtitle: String var imageUrl: URL ... }

ComponentModel

2. PROTOCOL-ORIENTED VIEWS

Components

UICollectionView

protocol Component {var view: UIView? { get }

func loadView()

}func configure(withModel: ComponentModel)

var preferredViewSize: CGSize { get }var layoutTraits: [LayoutTrait] { get }

UICollectionViewLayout

3. A DECLARATIVE API

$

Logic to load content Respond to Interactions

COMPONENTSCOMPONENT

MODELS

CONTENT OPERATIONSViewModelBuilder Content

BACKEND

MODELS

COMPONENTSCOMPONENT

MODELSCONTENT

OPERATIONS

DECLARERENDER

1. SHARED DATA MODEL

2. PROTOCOL-ORIENTED VIEWS

3. A DECLARATIVE API

THE HUB FRAMEWORK

DEMO

OPEN SOURCE! %

GITHUB.COM/JOHNSUNDELL

@JOHNSUNDELL