SlideShare uma empresa Scribd logo
1 de 48
Baixar para ler offline
Writing your App
Swiftly
Sommer Panage
Chorus Fitness
@sommer
Patterns!
Today, in 4 short tales
• Schrödinger's Result
• The Little Layout Engine that Could
• Swiftilocks and the Three View States
• Pete and the Repeated Code
The Demo App
Schrödinger's Result
Code in a box
func getFilms(completion: @escaping ([Film]?, APIError?) -> Void) {
let url = SWAPI.baseURL.appendingPathComponent(Endpoint.films.rawValue)
let task = self.session.dataTask(with: url) { (data, response, error) in
if let data = data {
do {
let jsonObject = try JSONSerialization.jsonObject(with: data, options: [])
if let films = SWAPI.decodeFilms(jsonObject: jsonObject) {
completion(films, nil)
} else {
completion(nil, .decoding)
}
} catch {
completion(nil, .server(originalError: error))
}
} else {
completion(nil, .server(originalError: error!))
}
}
task.resume()
}
What we think is happening…
What's actually
happening…
override func viewDidLoad() {
super.viewDidLoad()
apiClient.getFilms() { films, error in
if let films = films {
// Show film UI
if let error = error {
// Log warning...this is weird
}
} else if let error = error {
// Show error UI
} else {
// No results at all? Show error UI I guess?
}
}
}
Result open source framework by Rob Rix
Model our server interaction as it actually is - success / failure!
public enum Result<T, Error: Swift.Error>: ResultProtocol {
case success(T)
case failure(Error)
}
New, improved code
func getFilms(completion: @escaping (Result<[Film], APIError>) -> Void) {
let task = self.session
.dataTask(with: SWAPI.baseURL.appendingPathComponent(Endpoint.films.rawValue)) { (data, response, error) in
let result = Result(data, failWith: APIError.server(originalError: error!))
.flatMap { data in
Result<Any, AnyError>(attempt: { try JSONSerialization.jsonObject(with: data, options: []) })
.mapError { _ in APIError.decoding }
}
.flatMap { Result(SWAPI.decodeFilms(jsonObject: $0), failWith: .decoding) }
completion(result)
}
task.resume()
}
New, improved code
override func viewDidLoad() {
super.viewDidLoad()
apiClient.getFilms() { result in
switch result {
case .success(let films): print(films) // Show my UI!
case .failure(let error): print(error) // Show some error UI
}
}
}
The Moral of the Story
Using the Result enum allowed us to
• Model the sucess/failure of our server interaction more
correctly
• Thus simplify our view controller code.
The Little Layout Engine that
Could
Old-school
override func layoutSubviews() {
super.layoutSubviews()
// WHY AM I DOING THIS?!?!
}
What about Storyboards and Xibs?
• Working in teams becomes harder because...
• XML diffs
• Merge conflicts?!
• No constants
• Stringly typed identifiers
• Fragile connections
Autolayout: iOS 9+ APIs
init() {
super.init(frame: .zero)
addSubview(tableView)
// Autolayout: Table same size as parent
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true
}
Autolayout: Cartography by Robb Böhnke
init() {
super.init(frame: .zero)
addSubview(tableView)
// Autolayout: Table same size as parent
constrain(tableView, self) { table, parent in
table.edges == parent.edges
}
}
More Cartography
private let margin: CGFloat = 16
private let episodeLeftPadding: CGFloat = 8
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(episodeLabel)
contentView.addSubview(titleLabel)
constrain(episodeLabel, titleLabel, contentView) { episode, title, parent in
episode.leading == parent.leading + margin
episode.top == parent.top + margin
episode.bottom == parent.bottom - margin
title.leading == episode.trailing + episodeLeftPadding
title.trailing <= parent.trailing - margin
title.centerY == episode.centerY
}
}
The Moral of the Story
Using the Cartography framework harnesses Swift's
operator overloads to make programatic AutoLayout a
breeze!
Swiftilocks and the
Three View States
Swiftilocks and the Three View
States
LOADING
Swiftilocks and the Three View
States
SUCCESS
Swiftilocks and the Three View
States
ERROR
State management with bools
/// MainView.swift
var isLoading: Bool = false {
didSet {
errorView.isHidden = true
loadingView.isHidden = !isLoading
}
}
var isError: Bool = false {
didSet {
errorView.isHidden = !isError
loadingView.isHidden = true
}
}
var items: [MovieItem]? {
didSet {
tableView.reloadData()
}
}
/// MainViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
title = "Star Wars Films"
mainView.isLoading = true
apiClient.getFilms() { result in
DispatchQueue.main.async {
switch result {
case .success(let films):
self.mainView.items = films
.map { MovieItem(episodeID: $0.episodeID, title: $0.title) }
.sorted { $0.0.episodeID < $0.1.episodeID }
self.mainView.isLoading = false
self.mainView.isError = false
case .failure(let error):
self.mainView.isLoading = false
self.mainView.isError = true
}
}
}
}
Too many states!!
Data presence + state?!
Enums to the rescue!
final class MainView: UIView {
enum State {
case loading
case loaded(items: [MovieItem])
case error(message: String)
}
init(state: State) { ... }
// the rest of my class...
}
var state: State {
didSet {
switch state {
case .loading:
items = nil
loadingView.isHidden = false
errorView.isHidden = true
case .error(let message):
print(message)
items = nil
loadingView.isHidden = true
errorView.isHidden = false
case .loaded(let movieItems):
loadingView.isHidden = true
errorView.isHidden = true
items = movieItems
tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
title = "Star Wars Films"
mainView.state = .loading
apiClient.getFilms() { result in
DispatchQueue.main.async {
switch result {
case .success(let films):
let items = films
.map { MovieItem(episodeID: $0.episodeID, title: $0.title) }
.sorted { $0.0.episodeID < $0.1.episodeID }
self.mainView.state = .loaded(items: items)
case .failure(let error):
self.mainView.state = .error(message: "Error: (error.localizedDescription)")
}
}
}
}
The Moral of the Story
Modelling our view state with an enum with
associated values allows us to:
1. Simplify our VC
2. Avoid ambiguous state
3. Centralize our logic
It's better...but...
Pete and the Repeated Code.
Repeated code
var state: State {
didSet {
switch state {
case .loading:
text = nil
loadingView.isHidden = false
errorView.isHidden = true
case .error(let message):
print(message)
text = nil
loadingView.isHidden = true
errorView.isHidden = false
case .loaded(let text):
loadingView.isHidden = true
errorView.isHidden = true
text = text
tableView.reloadData()
}
}
}
Protocols save the day!!
• A shared interface of methods and properties
• Addresses a particular task
• Types adopting protocol need not be related
protocol DataLoading {
associatedtype Data
var state: ViewState<Data> { get set }
var loadingView: LoadingView { get }
var errorView: ErrorView { get }
func update()
}
enum ViewState<Content> {
case loading
case loaded(data: Content)
case error(message: String)
}
Default protocol implementation
extension DataLoading where Self: UIView {
func update() {
switch state {
case .loading:
loadingView.isHidden = false
errorView.isHidden = true
case .error(let error):
loadingView.isHidden = true
errorView.isHidden = false
Log.error(error)
case .loaded:
loadingView.isHidden = true
errorView.isHidden = true
}
}
}
Conforming to DataLoading
1. Provide an errorView variable
2. Provide an loadingView variable
3. Provide a state variable that take some sort of Data
4. Call update() whenever needed
DataLoading in our Main View
final class MainView: UIView, DataLoading {
let loadingView = LoadingView()
let errorView = ErrorView()
var state: ViewState<[MovieItem]> {
didSet {
update() // call update whenever we set our list of Movies
tableView.reloadData()
}
}
DataLoading in our Crawl View
class CrawlView: UIView, DataLoading {
let loadingView = LoadingView()
let errorView = ErrorView()
var state: ViewState<String> {
didSet {
update()
crawlLabel.text = state.data
}
}
The Moral of the Story
Decomposing functionality that is shared by non-
related objects into a protocol helps us
• Avoid duplicated code
• Consolidate our logic into one place
Conclusion
• Result: easily differentiate our success/error pathways
• Cartography: use operator overloading to make code more
readable
• ViewState enum: never have an ambigous view state!
• Protocols: define/decompose shared behaviors in unrelated
types
THANK YOU
Contact Me:
@sommer on Twitter
me@sommerpanage.com

Mais conteúdo relacionado

Mais procurados

Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testingVisual Engineering
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)James Titcumb
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICKonstantin Kudryashov
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony TechniquesKris Wallsmith
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the ASTJarrod Overson
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascriptkvangork
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Kris Wallsmith
 
스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내Jung Kim
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End DevsRebecca Murphey
 
PHP Language Trivia
PHP Language TriviaPHP Language Trivia
PHP Language TriviaNikita Popov
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsMark Baker
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KThomas Fuchs
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingSamuel ROZE
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationŁukasz Chruściel
 

Mais procurados (20)

Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
 
The jQuery Divide
The jQuery DivideThe jQuery Divide
The jQuery Divide
 
Workshop 5: JavaScript testing
Workshop 5: JavaScript testingWorkshop 5: JavaScript testing
Workshop 5: JavaScript testing
 
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
Mirror, mirror on the wall: Building a new PHP reflection library (DPC 2016)
 
Your JavaScript Library
Your JavaScript LibraryYour JavaScript Library
Your JavaScript Library
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
 
Advanced symfony Techniques
Advanced symfony TechniquesAdvanced symfony Techniques
Advanced symfony Techniques
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
 
Object-Oriented Javascript
Object-Oriented JavascriptObject-Oriented Javascript
Object-Oriented Javascript
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
 
Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)Doctrine MongoDB ODM (PDXPHP)
Doctrine MongoDB ODM (PDXPHP)
 
스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내스위프트를 여행하는 히치하이커를 위한 스타일 안내
스위프트를 여행하는 히치하이커를 위한 스타일 안내
 
Rust ⇋ JavaScript
Rust ⇋ JavaScriptRust ⇋ JavaScript
Rust ⇋ JavaScript
 
JavaScript Promise
JavaScript PromiseJavaScript Promise
JavaScript Promise
 
A New Baseline for Front-End Devs
A New Baseline for Front-End DevsA New Baseline for Front-End Devs
A New Baseline for Front-End Devs
 
PHP Language Trivia
PHP Language TriviaPHP Language Trivia
PHP Language Trivia
 
A Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP GeneratorsA Functional Guide to Cat Herding with PHP Generators
A Functional Guide to Cat Herding with PHP Generators
 
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2KZepto.js, a jQuery-compatible mobile JavaScript framework in 2K
Zepto.js, a jQuery-compatible mobile JavaScript framework in 2K
 
Introduction to CQRS and Event Sourcing
Introduction to CQRS and Event SourcingIntroduction to CQRS and Event Sourcing
Introduction to CQRS and Event Sourcing
 
Sylius and Api Platform The story of integration
Sylius and Api Platform The story of integrationSylius and Api Platform The story of integration
Sylius and Api Platform The story of integration
 

Destaque

20170302 tryswift tasting_tests
20170302 tryswift tasting_tests20170302 tryswift tasting_tests
20170302 tryswift tasting_testsKazuaki Matsuo
 
描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)Kenji Tanaka
 
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiReact Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiYukiya Nakagawa
 
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swift
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swiftみんなで Swift 復習会での談笑用スライド – 6th #minna_de_swift
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swiftTomohiro Kumagai
 
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafe
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafeSwift イニシャライザー復習会 #love_swift #akibaswift #21cafe
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafeTomohiro Kumagai
 
The Future of Mobile - Presented at SMX Munich
The Future of Mobile - Presented at SMX MunichThe Future of Mobile - Presented at SMX Munich
The Future of Mobile - Presented at SMX MunichEric Enge
 
Presentazione Bando Pre-Seed
Presentazione Bando Pre-SeedPresentazione Bando Pre-Seed
Presentazione Bando Pre-SeedLazio Innova
 
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介minneにおけるテスト〜リリース〜リリース後にやっている事の紹介
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介Masataka Kono
 
【掲載用】アウトプットし続ける技術20170314
【掲載用】アウトプットし続ける技術20170314【掲載用】アウトプットし続ける技術20170314
【掲載用】アウトプットし続ける技術20170314Hayashi Masayuki
 
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法Daisuke Nogami
 
H2O x mrubyで人はどれだけ幸せになれるのか
H2O x mrubyで人はどれだけ幸せになれるのかH2O x mrubyで人はどれだけ幸せになれるのか
H2O x mrubyで人はどれだけ幸せになれるのかIchito Nagata
 
スマホマーケットの概要と、 マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
スマホマーケットの概要と、 マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)Tokoroten Nakayama
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017John Maeda
 
Boletín 15/03/2017
Boletín 15/03/2017Boletín 15/03/2017
Boletín 15/03/2017Openbank
 
Personal effectiveness in the workplace
Personal effectiveness in the workplacePersonal effectiveness in the workplace
Personal effectiveness in the workplaceAngela Ihunweze
 
Gamification Workshop handouts
Gamification Workshop handoutsGamification Workshop handouts
Gamification Workshop handoutsBart Hufen
 
3DCGMeetup08_MayaRigSystem_mGear
3DCGMeetup08_MayaRigSystem_mGear3DCGMeetup08_MayaRigSystem_mGear
3DCGMeetup08_MayaRigSystem_mGearue_ta
 

Destaque (20)

20170302 tryswift tasting_tests
20170302 tryswift tasting_tests20170302 tryswift tasting_tests
20170302 tryswift tasting_tests
 
Client-Side Deep Learning
Client-Side Deep LearningClient-Side Deep Learning
Client-Side Deep Learning
 
Swift + GraphQL
Swift + GraphQLSwift + GraphQL
Swift + GraphQL
 
RxSwift x Realm
RxSwift x RealmRxSwift x Realm
RxSwift x Realm
 
描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)描画とビジネスをクリーンに分ける(公開用)
描画とビジネスをクリーンに分ける(公開用)
 
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigiReact Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
React Nativeはクロスプラットフォームモバイルアプリ開発の夢を見るか #DroidKaigi
 
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swift
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swiftみんなで Swift 復習会での談笑用スライド – 6th #minna_de_swift
みんなで Swift 復習会での談笑用スライド – 6th #minna_de_swift
 
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafe
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafeSwift イニシャライザー復習会 #love_swift #akibaswift #21cafe
Swift イニシャライザー復習会 #love_swift #akibaswift #21cafe
 
The Future of Mobile - Presented at SMX Munich
The Future of Mobile - Presented at SMX MunichThe Future of Mobile - Presented at SMX Munich
The Future of Mobile - Presented at SMX Munich
 
Presentazione Bando Pre-Seed
Presentazione Bando Pre-SeedPresentazione Bando Pre-Seed
Presentazione Bando Pre-Seed
 
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介minneにおけるテスト〜リリース〜リリース後にやっている事の紹介
minneにおけるテスト〜リリース〜リリース後にやっている事の紹介
 
【掲載用】アウトプットし続ける技術20170314
【掲載用】アウトプットし続ける技術20170314【掲載用】アウトプットし続ける技術20170314
【掲載用】アウトプットし続ける技術20170314
 
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法
決定版:サービスの盛り上がり具合をユーザの数(DAU)から読み解く方法
 
H2O x mrubyで人はどれだけ幸せになれるのか
H2O x mrubyで人はどれだけ幸せになれるのかH2O x mrubyで人はどれだけ幸せになれるのか
H2O x mrubyで人はどれだけ幸せになれるのか
 
スマホマーケットの概要と、 マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)スマホマーケットの概要と、マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
スマホマーケットの概要と、 マーケティングの失敗例と改善 (アナリティクス アソシエーション 特別セミナー)
 
Design in Tech Report 2017
Design in Tech Report 2017Design in Tech Report 2017
Design in Tech Report 2017
 
Boletín 15/03/2017
Boletín 15/03/2017Boletín 15/03/2017
Boletín 15/03/2017
 
Personal effectiveness in the workplace
Personal effectiveness in the workplacePersonal effectiveness in the workplace
Personal effectiveness in the workplace
 
Gamification Workshop handouts
Gamification Workshop handoutsGamification Workshop handouts
Gamification Workshop handouts
 
3DCGMeetup08_MayaRigSystem_mGear
3DCGMeetup08_MayaRigSystem_mGear3DCGMeetup08_MayaRigSystem_mGear
3DCGMeetup08_MayaRigSystem_mGear
 

Semelhante a Writing your App Swiftly with Patterns

Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Robert DeLuca
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gearsdion
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenerytoddbr
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 
SQLite and ORM Binding - Part 1 - Transcript.pdf
SQLite and ORM Binding - Part 1 - Transcript.pdfSQLite and ORM Binding - Part 1 - Transcript.pdf
SQLite and ORM Binding - Part 1 - Transcript.pdfShaiAlmog1
 
Our challenge for Bulkload reliability improvement
Our challenge for Bulkload reliability  improvementOur challenge for Bulkload reliability  improvement
Our challenge for Bulkload reliability improvementSatoshi Akama
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfacesmaccman
 
Building a Cloud API Server using Play(SCALA) & Riak
Building a Cloud API Server using  Play(SCALA) & Riak Building a Cloud API Server using  Play(SCALA) & Riak
Building a Cloud API Server using Play(SCALA) & Riak RajthilakMCA
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingNatasha Murashev
 
Practialpop 160510130818
Practialpop 160510130818Practialpop 160510130818
Practialpop 160510130818Shahzain Saeed
 
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in SwiftMCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in SwiftPROIDEA
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsMike Subelsky
 
Scti 2011 minicurso jquery
Scti 2011 minicurso jqueryScti 2011 minicurso jquery
Scti 2011 minicurso jqueryciberglo
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testingsmontanari
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testingryan_chambers
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POPNatasha Murashev
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsRobert Nyman
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsJeff Durta
 

Semelhante a Writing your App Swiftly with Patterns (20)

Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 
Future of Web Apps: Google Gears
Future of Web Apps: Google GearsFuture of Web Apps: Google Gears
Future of Web Apps: Google Gears
 
Javascript first-class citizenery
Javascript first-class citizeneryJavascript first-class citizenery
Javascript first-class citizenery
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 
iOS Talks 6: Unit Testing
iOS Talks 6: Unit TestingiOS Talks 6: Unit Testing
iOS Talks 6: Unit Testing
 
SQLite and ORM Binding - Part 1 - Transcript.pdf
SQLite and ORM Binding - Part 1 - Transcript.pdfSQLite and ORM Binding - Part 1 - Transcript.pdf
SQLite and ORM Binding - Part 1 - Transcript.pdf
 
Our challenge for Bulkload reliability improvement
Our challenge for Bulkload reliability  improvementOur challenge for Bulkload reliability  improvement
Our challenge for Bulkload reliability improvement
 
Asynchronous Interfaces
Asynchronous InterfacesAsynchronous Interfaces
Asynchronous Interfaces
 
Building a Cloud API Server using Play(SCALA) & Riak
Building a Cloud API Server using  Play(SCALA) & Riak Building a Cloud API Server using  Play(SCALA) & Riak
Building a Cloud API Server using Play(SCALA) & Riak
 
Dojo and Adobe AIR
Dojo and Adobe AIRDojo and Adobe AIR
Dojo and Adobe AIR
 
Practical Protocol-Oriented-Programming
Practical Protocol-Oriented-ProgrammingPractical Protocol-Oriented-Programming
Practical Protocol-Oriented-Programming
 
Practialpop 160510130818
Practialpop 160510130818Practialpop 160510130818
Practialpop 160510130818
 
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in SwiftMCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
MCE^3 - Natasha Murashev - Practical Protocol-Oriented Programming in Swift
 
SproutCore and the Future of Web Apps
SproutCore and the Future of Web AppsSproutCore and the Future of Web Apps
SproutCore and the Future of Web Apps
 
Scti 2011 minicurso jquery
Scti 2011 minicurso jqueryScti 2011 minicurso jquery
Scti 2011 minicurso jquery
 
Single page webapps & javascript-testing
Single page webapps & javascript-testingSingle page webapps & javascript-testing
Single page webapps & javascript-testing
 
Automated javascript unit testing
Automated javascript unit testingAutomated javascript unit testing
Automated javascript unit testing
 
Swift Delhi: Practical POP
Swift Delhi: Practical POPSwift Delhi: Practical POP
Swift Delhi: Practical POP
 
WebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.jsWebAPIs & WebRTC - Spotify/sthlm.js
WebAPIs & WebRTC - Spotify/sthlm.js
 
Adding a modern twist to legacy web applications
Adding a modern twist to legacy web applicationsAdding a modern twist to legacy web applications
Adding a modern twist to legacy web applications
 

Último

call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️Delhi Call girls
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...kellynguyen01
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsArshad QA
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto González Trastoy
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVshikhaohhpro
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...MyIntelliSource, Inc.
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsAndolasoft Inc
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...MyIntelliSource, Inc.
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️anilsa9823
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comFatema Valibhai
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Steffen Staab
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...Health
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 

Último (20)

call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
call girls in Vaishali (Ghaziabad) 🔝 >༒8448380779 🔝 genuine Escort Service 🔝✔️✔️
 
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
Short Story: Unveiling the Reasoning Abilities of Large Language Models by Ke...
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
Optimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTVOptimizing AI for immediate response in Smart CCTV
Optimizing AI for immediate response in Smart CCTV
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
Steps To Getting Up And Running Quickly With MyTimeClock Employee Scheduling ...
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
How To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.jsHow To Use Server-Side Rendering with Nuxt.js
How To Use Server-Side Rendering with Nuxt.js
 
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS LiveVip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
Vip Call Girls Noida ➡️ Delhi ➡️ 9999965857 No Advance 24HRS Live
 
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
Try MyIntelliAccount Cloud Accounting Software As A Service Solution Risk Fre...
 
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂️
CALL ON ➥8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂️
 
HR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.comHR Software Buyers Guide in 2024 - HRSoftware.com
HR Software Buyers Guide in 2024 - HRSoftware.com
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 

Writing your App Swiftly with Patterns

  • 1. Writing your App Swiftly Sommer Panage Chorus Fitness @sommer
  • 2.
  • 3.
  • 5. Today, in 4 short tales • Schrödinger's Result • The Little Layout Engine that Could • Swiftilocks and the Three View States • Pete and the Repeated Code
  • 7.
  • 9. Code in a box func getFilms(completion: @escaping ([Film]?, APIError?) -> Void) { let url = SWAPI.baseURL.appendingPathComponent(Endpoint.films.rawValue) let task = self.session.dataTask(with: url) { (data, response, error) in if let data = data { do { let jsonObject = try JSONSerialization.jsonObject(with: data, options: []) if let films = SWAPI.decodeFilms(jsonObject: jsonObject) { completion(films, nil) } else { completion(nil, .decoding) } } catch { completion(nil, .server(originalError: error)) } } else { completion(nil, .server(originalError: error!)) } } task.resume() }
  • 10. What we think is happening…
  • 11. What's actually happening… override func viewDidLoad() { super.viewDidLoad() apiClient.getFilms() { films, error in if let films = films { // Show film UI if let error = error { // Log warning...this is weird } } else if let error = error { // Show error UI } else { // No results at all? Show error UI I guess? } } }
  • 12. Result open source framework by Rob Rix Model our server interaction as it actually is - success / failure! public enum Result<T, Error: Swift.Error>: ResultProtocol { case success(T) case failure(Error) }
  • 13. New, improved code func getFilms(completion: @escaping (Result<[Film], APIError>) -> Void) { let task = self.session .dataTask(with: SWAPI.baseURL.appendingPathComponent(Endpoint.films.rawValue)) { (data, response, error) in let result = Result(data, failWith: APIError.server(originalError: error!)) .flatMap { data in Result<Any, AnyError>(attempt: { try JSONSerialization.jsonObject(with: data, options: []) }) .mapError { _ in APIError.decoding } } .flatMap { Result(SWAPI.decodeFilms(jsonObject: $0), failWith: .decoding) } completion(result) } task.resume() }
  • 14. New, improved code override func viewDidLoad() { super.viewDidLoad() apiClient.getFilms() { result in switch result { case .success(let films): print(films) // Show my UI! case .failure(let error): print(error) // Show some error UI } } }
  • 15. The Moral of the Story Using the Result enum allowed us to • Model the sucess/failure of our server interaction more correctly • Thus simplify our view controller code.
  • 16. The Little Layout Engine that Could
  • 17. Old-school override func layoutSubviews() { super.layoutSubviews() // WHY AM I DOING THIS?!?! }
  • 18. What about Storyboards and Xibs? • Working in teams becomes harder because... • XML diffs • Merge conflicts?! • No constants • Stringly typed identifiers • Fragile connections
  • 19. Autolayout: iOS 9+ APIs init() { super.init(frame: .zero) addSubview(tableView) // Autolayout: Table same size as parent tableView.translatesAutoresizingMaskIntoConstraints = false tableView.topAnchor.constraint(equalTo: self.topAnchor).isActive = true tableView.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true tableView.leadingAnchor.constraint(equalTo: self.leadingAnchor).isActive = true tableView.trailingAnchor.constraint(equalTo: self.trailingAnchor).isActive = true }
  • 20. Autolayout: Cartography by Robb Böhnke init() { super.init(frame: .zero) addSubview(tableView) // Autolayout: Table same size as parent constrain(tableView, self) { table, parent in table.edges == parent.edges } }
  • 21. More Cartography private let margin: CGFloat = 16 private let episodeLeftPadding: CGFloat = 8 override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) contentView.addSubview(episodeLabel) contentView.addSubview(titleLabel) constrain(episodeLabel, titleLabel, contentView) { episode, title, parent in episode.leading == parent.leading + margin episode.top == parent.top + margin episode.bottom == parent.bottom - margin title.leading == episode.trailing + episodeLeftPadding title.trailing <= parent.trailing - margin title.centerY == episode.centerY } }
  • 22. The Moral of the Story Using the Cartography framework harnesses Swift's operator overloads to make programatic AutoLayout a breeze!
  • 24. Swiftilocks and the Three View States LOADING
  • 25. Swiftilocks and the Three View States SUCCESS
  • 26. Swiftilocks and the Three View States ERROR
  • 27.
  • 28. State management with bools /// MainView.swift var isLoading: Bool = false { didSet { errorView.isHidden = true loadingView.isHidden = !isLoading } } var isError: Bool = false { didSet { errorView.isHidden = !isError loadingView.isHidden = true } } var items: [MovieItem]? { didSet { tableView.reloadData() } }
  • 29. /// MainViewController.swift override func viewDidLoad() { super.viewDidLoad() title = "Star Wars Films" mainView.isLoading = true apiClient.getFilms() { result in DispatchQueue.main.async { switch result { case .success(let films): self.mainView.items = films .map { MovieItem(episodeID: $0.episodeID, title: $0.title) } .sorted { $0.0.episodeID < $0.1.episodeID } self.mainView.isLoading = false self.mainView.isError = false case .failure(let error): self.mainView.isLoading = false self.mainView.isError = true } } } }
  • 31. Data presence + state?!
  • 32. Enums to the rescue! final class MainView: UIView { enum State { case loading case loaded(items: [MovieItem]) case error(message: String) } init(state: State) { ... } // the rest of my class... }
  • 33. var state: State { didSet { switch state { case .loading: items = nil loadingView.isHidden = false errorView.isHidden = true case .error(let message): print(message) items = nil loadingView.isHidden = true errorView.isHidden = false case .loaded(let movieItems): loadingView.isHidden = true errorView.isHidden = true items = movieItems tableView.reloadData() } } }
  • 34. override func viewDidLoad() { super.viewDidLoad() title = "Star Wars Films" mainView.state = .loading apiClient.getFilms() { result in DispatchQueue.main.async { switch result { case .success(let films): let items = films .map { MovieItem(episodeID: $0.episodeID, title: $0.title) } .sorted { $0.0.episodeID < $0.1.episodeID } self.mainView.state = .loaded(items: items) case .failure(let error): self.mainView.state = .error(message: "Error: (error.localizedDescription)") } } } }
  • 35. The Moral of the Story Modelling our view state with an enum with associated values allows us to: 1. Simplify our VC 2. Avoid ambiguous state 3. Centralize our logic
  • 37. Pete and the Repeated Code.
  • 38. Repeated code var state: State { didSet { switch state { case .loading: text = nil loadingView.isHidden = false errorView.isHidden = true case .error(let message): print(message) text = nil loadingView.isHidden = true errorView.isHidden = false case .loaded(let text): loadingView.isHidden = true errorView.isHidden = true text = text tableView.reloadData() } } }
  • 39. Protocols save the day!! • A shared interface of methods and properties • Addresses a particular task • Types adopting protocol need not be related
  • 40. protocol DataLoading { associatedtype Data var state: ViewState<Data> { get set } var loadingView: LoadingView { get } var errorView: ErrorView { get } func update() }
  • 41. enum ViewState<Content> { case loading case loaded(data: Content) case error(message: String) }
  • 42. Default protocol implementation extension DataLoading where Self: UIView { func update() { switch state { case .loading: loadingView.isHidden = false errorView.isHidden = true case .error(let error): loadingView.isHidden = true errorView.isHidden = false Log.error(error) case .loaded: loadingView.isHidden = true errorView.isHidden = true } } }
  • 43. Conforming to DataLoading 1. Provide an errorView variable 2. Provide an loadingView variable 3. Provide a state variable that take some sort of Data 4. Call update() whenever needed
  • 44. DataLoading in our Main View final class MainView: UIView, DataLoading { let loadingView = LoadingView() let errorView = ErrorView() var state: ViewState<[MovieItem]> { didSet { update() // call update whenever we set our list of Movies tableView.reloadData() } }
  • 45. DataLoading in our Crawl View class CrawlView: UIView, DataLoading { let loadingView = LoadingView() let errorView = ErrorView() var state: ViewState<String> { didSet { update() crawlLabel.text = state.data } }
  • 46. The Moral of the Story Decomposing functionality that is shared by non- related objects into a protocol helps us • Avoid duplicated code • Consolidate our logic into one place
  • 47. Conclusion • Result: easily differentiate our success/error pathways • Cartography: use operator overloading to make code more readable • ViewState enum: never have an ambigous view state! • Protocols: define/decompose shared behaviors in unrelated types
  • 48. THANK YOU Contact Me: @sommer on Twitter me@sommerpanage.com