SlideShare a Scribd company logo
What 100M downloads
taught us about
iOS architectures
Francesco Di Lorenzo // @frankdilo
January 23, 2018
Learn Swift Milan — Meetup #3
What 100M downloads taught us about iOS architectures
What 100M downloads taught us about iOS architectures
github.com/bendingspoons/katana-swift
Motivation
• Our code must manage more state than ever
before: server responses and cached data, as well
as locally created data that has not yet been
persisted to the server
• This complexity is difficult to handle as we're mixing
two concepts that are very hard for the human
mind to reason about: mutation and
asynchronicity.
Courtesy of the Redux docs
Mutation + Asynchronicity
Great in separation but together they are like: Mentos + Coke
+
Mutation + Asynchronicity
Great in separation but together they are like: Mentos + Coke
+-
0
// State
struct AppState: State {
var counter = 0
}
// Actions
struct Increment: AppAction {
func updateState(state: inout AppState) {
state.counter += 1
}
}
struct Decrement: AppAction {
func updateState(state: inout AppState) {
state.counter -= 1
}
}
+-
0
+-
1
AppState(counter: 0) AppState(counter: 1)
dispatch(Increment())
Side Effects
• Handle complex flows that
cannot be described as
synchronous state mutations
(API calls, Image processing,
async tasks, …)
class AppDependencies: SideEffectDependencyContainer {
lazy var apiManager = ApiManager()
lazy var analyticsTracker = AnalyticsTracker()
// …
}
struct DownloadFeed: AppAction, AppActionWithSideEffect {
func sideEffect(current: AppState,
previous: AppState,
dispatch: @escaping StoreDispatch,
dependencies: AppDependencies) {
dependencies.apiManager.downloadFeed { feedItems in
dispatch(FeedDownloaded(items: feedItems))
}
}
}
What’s cool about
this architecture?
• It enforces an unidirectional data flow: this makes
the logic predictable and easier to understand
• It encourages data normalization, so that you don't
end up with multiple, independent copies of the
same data that are unaware of one another
• It allows the creation of powerful debugging tools
Powerful Debugging Tools
Highly Testable
Middleware
let myMiddleware: StoreMiddleware = { getState, dispatch in
return { next in
return { action in
let previousState = getState()
next(action)
let currentState = getState()
// do something...
}
}
}
• Persist and restore the app state

• Track metrics by detecting when an action is dispatched
or when the state changes

• Debugging: log actions, measure execution time

• …
TrackEvent<AppState, ShowColorPage>(
eventName: "open_page",
eventData: { previousState, currentState, action in
let isCompleted = currentState.completed.contains(action.id)
return [
"id": action.id,
"is_user_custom": action.userCustom,
"completed": isCompleted
]
}
)
Tempura
Available Architectures
MVC MVVMMVP VIPER
Ease of Use
Separation
of Concerns
Testability
Available Architectures
MVC MVVMMVP VIPER
Ease of Use
Separation
of Concerns
Testability
How it all works together
State
Actions
View
Controller
View Model
View
struct AppState: State {
var counter = 0
}
+-
0
struct CounterViewModel: ViewModelWithState {
var counterText = ""
init(state: AppState) {
self.counterText = "(state.counter)"
}
}
class CounterView: UIView, ViewControllerModellableView {
// MARK: Subviews
var counterLabel = UILabel()
var incrementButton = UIButton()
var decrementButton = UIButton()
// MARK: Interactions
var userDidTapIncrease: Interaction?
var userDidTapDecrease: Interaction?
// …
+-
0
func setup() {
self.addSubview(counterLabel)
self.addSubview(incrementButton)
self.addSubview(decrementButton)
self.incrementButton.on(.touchUpInside) { [weak self] _ in
self?.userDidTapIncrease?()
}
self.decrementButton.on(.touchUpInside) { [weak self] _ in
self?.userDidTapDecrease?()
}
}
+-
0
func update(oldModel: CounterViewModel?) {
self.counterLabel.text = self.model.counterText
}
+-
0
+-
1
dispatch(Increment())
class CounterViewController: ViewController<CounterView> {
override func setupInteraction() {
self.rootView.userDidTapIncrease = { [weak self] in
self?.dispatch(Increment())
}
self.rootView.userDidTapDecrease = { [weak self] in
self?.dispatch(Decrement())
}
}
}
+-
1
Does this scale?
View composition
EditorView:
ModellableView
struct EditorViewModel: ViewModel {
var timeline: Timeline
var settings: CompositionSettings
var isPlaying: Bool
var isAddPopupOpen: Bool
...
}
36 properties
struct VideoAreaViewModel: ViewModel {
var timeline: Timeline
var settings: CompositionSettings
var isPlaying: Bool
var isAddPopupOpen: Bool
...
}
View composition
EditingArea:
ModellableView
36 20 properties
EditingAreaViewModel(editor: EditorViewModel)
View composition
VideoArea:
ModellableView
struct VideoAreaViewModel: ViewModel {
var timeline: Timeline
var settings: CompositionSettings
var isPlaying: Bool
var isAddPopupOpen: Bool
...
}
36 12 properties
VideoAreaViewModel(editor: EditingAreaViewModel)
View composition
Switch:
View
var isOn: Bool
36 1 property
Navigation
• Navigate by dispatching Actions
• Isolate View Controllers presentation logic
• How do we reconcile navigation state managed by
UIKit and app state managed by Katana? 🤔
• Two main navigation actions: Show, Hide
• View Controllers must implement the Routable protocol
dispatch(Show(Screen.mainEditor))
dispatch(Hide())
enum Screen: String {
case mainTabbar
case feed
case feedSectionDetail
case createArt
case createArtFromPhoto
}
extension CreateArtStack: Routable {
var routeIdentifier: RouteElementIdentifier {
return Screen.createArt.rawValue
}
...
...


var navigationConfiguration:[NavigationSource: NavigationOption] {
return [
.show(Screen.createArtFromPhoto): .presentModally({
return CreateArtFromPhotoVC(store: self.store)
}),
.hide(Screen.createArtFromPhoto): .pop
]
}
References
• Katana — github.com/bendingspoons/katana-swift
• Tempura will be open sourced soon
• Want to know more? bendingspoons.com
Francesco Di Lorenzo // @frankdilo
That’s it! Thanks 🙌

More Related Content

PPTX
From zero to hero with the reactive extensions for java script
PPTX
From zero to hero with the reactive extensions for JavaScript
PDF
Knockout mvvm-m6-slides
PDF
Building Testable Reactive Apps with MVI
PDF
ASP.NET Page life cycle and ViewState
PDF
Angular js meetup
PDF
An introduction to React.js
PPTX
React, Flux and a little bit of Redux
From zero to hero with the reactive extensions for java script
From zero to hero with the reactive extensions for JavaScript
Knockout mvvm-m6-slides
Building Testable Reactive Apps with MVI
ASP.NET Page life cycle and ViewState
Angular js meetup
An introduction to React.js
React, Flux and a little bit of Redux

What's hot (20)

PDF
Aspnet Life Cycles Events
PPTX
SUGCon 2014 Sitecore MVC
PDF
React JS - Introduction
PPTX
React + Redux + TypeScript === ♥
PPTX
reactJS
PPTX
Introduction to react js
PDF
PPTX
A Brief Introduction to React.js
PDF
Cleaning your architecture with android architecture components
PDF
ASP.NET Internals
PPTX
BackboneJS + ReactJS
PPTX
Intro to React
PDF
Building Modern Web Applications using React and Redux
PDF
Thinking metrics on React apps
PPTX
Introduction to React and MobX
PPTX
Android Architectures
PDF
React vs-angular-mobile
PDF
Introduction to React & Redux
DOC
Page life cycle
Aspnet Life Cycles Events
SUGCon 2014 Sitecore MVC
React JS - Introduction
React + Redux + TypeScript === ♥
reactJS
Introduction to react js
A Brief Introduction to React.js
Cleaning your architecture with android architecture components
ASP.NET Internals
BackboneJS + ReactJS
Intro to React
Building Modern Web Applications using React and Redux
Thinking metrics on React apps
Introduction to React and MobX
Android Architectures
React vs-angular-mobile
Introduction to React & Redux
Page life cycle
Ad

Similar to What 100M downloads taught us about iOS architectures (20)

PPTX
Battle of React State Managers in frontend applications
PPTX
iOS Architectures
PDF
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
PPTX
Kakfa summit london 2019 - the art of the event-streaming app
PDF
A Blog About Using State in Next.js: Valuable Insights
PDF
Mobile Software Engineering Crash Course - C06 WindowsPhone
PDF
The art of the event streaming application: streams, stream processors and sc...
PDF
Kafka summit SF 2019 - the art of the event-streaming app
PDF
Android architecture components - how they fit in good old architectural patt...
PPTX
Windows Store app using XAML and C#: Enterprise Product Development
PDF
Windows phone 7 series
PDF
A Journey with React
PPTX
Intro react js
PDF
[Codecamp 2016] Going functional with flyd and react
PDF
MongoDB Stitch Tutorial
PDF
React state management with Redux and MobX
PDF
React & The Art of Managing Complexity
PPTX
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
PPTX
[NDC 2019] Enterprise-Grade Serverless
PDF
Hello, ReactorKit 
Battle of React State Managers in frontend applications
iOS Architectures
The Art of The Event Streaming Application: Streams, Stream Processors and Sc...
Kakfa summit london 2019 - the art of the event-streaming app
A Blog About Using State in Next.js: Valuable Insights
Mobile Software Engineering Crash Course - C06 WindowsPhone
The art of the event streaming application: streams, stream processors and sc...
Kafka summit SF 2019 - the art of the event-streaming app
Android architecture components - how they fit in good old architectural patt...
Windows Store app using XAML and C#: Enterprise Product Development
Windows phone 7 series
A Journey with React
Intro react js
[Codecamp 2016] Going functional with flyd and react
MongoDB Stitch Tutorial
React state management with Redux and MobX
React & The Art of Managing Complexity
[NDC 2019] Functions 2.0: Enterprise-Grade Serverless
[NDC 2019] Enterprise-Grade Serverless
Hello, ReactorKit 
Ad

Recently uploaded (20)

PDF
STKI Israel Market Study 2025 version august
PDF
Zenith AI: Advanced Artificial Intelligence
PDF
project resource management chapter-09.pdf
PDF
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
PDF
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
PPTX
Modernising the Digital Integration Hub
PDF
DP Operators-handbook-extract for the Mautical Institute
PPTX
cloud_computing_Infrastucture_as_cloud_p
PDF
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
PDF
Hybrid model detection and classification of lung cancer
PPTX
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
PDF
Architecture types and enterprise applications.pdf
PDF
NewMind AI Weekly Chronicles - August'25-Week II
PPTX
O2C Customer Invoices to Receipt V15A.pptx
PDF
Assigned Numbers - 2025 - Bluetooth® Document
PPTX
The various Industrial Revolutions .pptx
PDF
WOOl fibre morphology and structure.pdf for textiles
PDF
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
PPTX
OMC Textile Division Presentation 2021.pptx
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
STKI Israel Market Study 2025 version august
Zenith AI: Advanced Artificial Intelligence
project resource management chapter-09.pdf
TrustArc Webinar - Click, Consent, Trust: Winning the Privacy Game
From MVP to Full-Scale Product A Startup’s Software Journey.pdf
Modernising the Digital Integration Hub
DP Operators-handbook-extract for the Mautical Institute
cloud_computing_Infrastucture_as_cloud_p
Profit Center Accounting in SAP S/4HANA, S4F28 Col11
Hybrid model detection and classification of lung cancer
MicrosoftCybserSecurityReferenceArchitecture-April-2025.pptx
Architecture types and enterprise applications.pdf
NewMind AI Weekly Chronicles - August'25-Week II
O2C Customer Invoices to Receipt V15A.pptx
Assigned Numbers - 2025 - Bluetooth® Document
The various Industrial Revolutions .pptx
WOOl fibre morphology and structure.pdf for textiles
Transform Your ITIL® 4 & ITSM Strategy with AI in 2025.pdf
OMC Textile Division Presentation 2021.pptx
Group 1 Presentation -Planning and Decision Making .pptx

What 100M downloads taught us about iOS architectures