Download - Swift 2.2 Design Patterns CocoaConf Austin 2016

Transcript
Page 1: Swift 2.2 Design Patterns CocoaConf Austin 2016

Swift 2.2 Design Patterns

COCOACONF AUSTIN APRIL 2016

Skyline Credit: User:Argash [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

@CarlBrwn

Page 2: Swift 2.2 Design Patterns CocoaConf Austin 2016

Swift 2.2 Design Patterns

COCOACONF AUSTIN APRIL 2016

Skyline Credit: User:Argash [GFDL (http://www.gnu.org/copyleft/fdl.html) or CC BY-SA 3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

@CarlBrwn

Page 3: Swift 2.2 Design Patterns CocoaConf Austin 2016

[:]?

So, who is this idiot, anyway?

INTRODUCTION

@CarlBrwn

Page 4: Swift 2.2 Design Patterns CocoaConf Austin 2016
Page 5: Swift 2.2 Design Patterns CocoaConf Austin 2016

These mean a lot of different things to different people.

Hopefully they’re of some use to you.

WIDELY RECOGNIZED, BUT NOT UNDISPUTED

Page 6: Swift 2.2 Design Patterns CocoaConf Austin 2016

These mean a lot of different things to different people.

Hopefully they’re of some use to you.

WIDELY RECOGNIZED, BUT NOT UNDISPUTED

[:]?

Critical Concept in Software Engineering?Some think so, others disagree.

[:]?Simple Enumeration of

Weaknesses in C++See http://www.norvig.com/design-

patterns/[:]?

Just Shared Vocabulary?

Page 7: Swift 2.2 Design Patterns CocoaConf Austin 2016

So, Let’s talk about Swift (2.2 Version)

PATTERNS ARE LANGUAGE SPECIFIC

[:]?

Critical Concept in Software Engineering?Some think so, others disagree.

[:]?Simple Enumeration of

Weaknesses in C++See http://www.norvig.com/design-

patterns/[:]?

Just Shared Vocabulary?

Page 8: Swift 2.2 Design Patterns CocoaConf Austin 2016

So, Let’s talk about Swift (2.2 Version)

& Cocoa

PATTERNS ARE LANGUAGE (& FRAMEWORK) SPECIFIC

[:]?

Critical Concept in Software Engineering?Some think so, others disagree.

[:]?Simple Enumeration of

Weaknesses in C++See http://www.norvig.com/design-

patterns/[:]?

Just Shared Vocabulary?

Page 9: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Page 10: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Classic Cocoa Design Patterns as implemented in Swift

Page 11: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Classic Cocoa Design Patterns as implemented in SwiftSome Gang of Four Patterns that lend

themselves to Swift

Page 12: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Classic Cocoa Design Patterns as implemented in SwiftSome Gang of Four Patterns that lend

themselves to SwiftPatterns Apple Documents for Swift

Page 13: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Classic Cocoa Design Patterns as implemented in SwiftSome Gang of Four Patterns that lend

themselves to SwiftPatterns Apple Documents for SwiftPatterns from Other Languages

Page 14: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PATTERN SOURCES FOR TODAY

8

Classic Cocoa Design Patterns as implemented in SwiftSome Gang of Four Patterns that lend

themselves to SwiftPatterns Apple Documents for SwiftPatterns from Other LanguagesInteresting/Potential Swift-specific Patterns

Page 15: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

DELEGATE PATTERN

9

Cocoa is said to favor “Composition over Inheritance.” Delegation is one of the hallmarks of that strategy. UITableViewDataSource and UITableViewDelegate are examples.

CLASSIC COCOA PATTERN

Page 16: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

DELEGATE PATTERN

9

Cocoa is said to favor “Composition over Inheritance.” Delegation is one of the hallmarks of that strategy. UITableViewDataSource and UITableViewDelegate are examples.

CLASSIC COCOA PATTERN

[:]?Eases ConstructionThis is a big reason why we don’t have to use the “Factory Pattern” in Cocoa/Swift

Page 17: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

DELEGATE PATTERN IN SWIFT

10

var myDS : UITableViewDataSource?

let myTVC = UITableViewController() let myTV = myTVC.tableView

let num = myDS?.tableView(myTV, numberOfRowsInSection: 0)

let firstHeader = myDS?.tableView?(myTV, titleForHeaderInSection: 0)

Page 18: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

DELEGATE PATTERN IN SWIFT

10

var myDS : UITableViewDataSource?

let myTVC = UITableViewController() let myTV = myTVC.tableView

let num = myDS?.tableView(myTV, numberOfRowsInSection: 0)

let firstHeader = myDS?.tableView?(myTV, titleForHeaderInSection: 0)

1Test Delegate OptionalThe delegate itself must not be nil (check with ? and don’t (EVER) use !)

2Test Method ExistsPut ? after method call to test for @optional implementation

Page 19: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

ERROR HANDLING PATTERN

11

In Cocoa, methods that produce errors take an NSError pointer parameter last parameter.

In Swift 2, this is converted to a thrown ErrorType

NEW IN SWIFT 2 - HOOKS INTO COCOA’S (NSError**)

Page 20: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

ERROR HANDLING PATTERN

11

In Cocoa, methods that produce errors take an NSError pointer parameter last parameter.

In Swift 2, this is converted to a thrown ErrorType

NEW IN SWIFT 2 - HOOKS INTO COCOA’S (NSError**)

[]Not JAva’s Throwtry on each line that might throw catch for blocks

Page 21: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

ERROR HANDLING PATTERN IN SWIFT

12

- (BOOL)removeItemAtURL:(NSURL *)URL error:(NSError **)error { NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *URL = [NSURL fileURLWithPath:@"/path/to/file"]; NSError *error = nil; BOOL success = [fileManager removeItemAtURL:URL error:&error]; if (!success) { NSLog(@"Error: %@", error.domain); } }

Page 22: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

ERROR HANDLING PATTERN IN SWIFT

12

func removeItemAtURL(URL: NSURL) throws { let fileManager = NSFileManager.defaultManager() let URL = NSURL.fileURLWithPath("/path/to/file") do { try fileManager.removeItemAtURL(URL) } catch let error as NSError { print("Error: \(error.domain)") } }

- (BOOL)removeItemAtURL:(NSURL *)URL error:(NSError **)error { NSFileManager *fileManager = [NSFileManager defaultManager]; NSURL *URL = [NSURL fileURLWithPath:@"/path/to/file"]; NSError *error = nil; BOOL success = [fileManager removeItemAtURL:URL error:&error]; if (!success) { NSLog(@"Error: %@", error.domain); } }

Page 23: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

OBSERVER PATTERN

13

Key-Value Observing lets you observe any well-behaved Cocoa property (getter/setter).

It works in Swift *As Long As* the target isKindOf: NSObject

KVO IN SWIFT

Page 24: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

OBSERVER PATTERN IN SWIFT

14

Page 25: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

OBSERVER PATTERN IN SWIFT

14

objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New, context: &myContext)

Page 26: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

OBSERVER PATTERN IN SWIFT

14

objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New, context: &myContext)

override func observeValueForKeyPath(keyPath:String?, ofObject object: AnyObject?, change: [ String : AnyObject ]?, context: UnsafeMutablePointer <Void>) {

if context == &myContext { if let newValue = change?[NSKeyValueChangeNewKey] { print("Date changed: \(newValue)") } } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)

} }

Page 27: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

OBSERVER PATTERN IN SWIFT

14

objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New, context: &myContext)

override func observeValueForKeyPath(keyPath:String?, ofObject object: AnyObject?, change: [ String : AnyObject ]?, context: UnsafeMutablePointer <Void>) {

if context == &myContext { if let newValue = change?[NSKeyValueChangeNewKey] { print("Date changed: \(newValue)") } } else { super.observeValueForKeyPath(keyPath, ofObject: object, change: change, context: context)

} }

objectToObserve.removeObserver(self, forKeyPath: "myDate", context: &myContext)

Page 28: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SWIFT-NATIVE KVO *MAYBE* IN SWIFT 4

15

Page 29: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

TARGET-ACTION PATTERN

16

In Objective-C, we use @selector to wrap the method name when adding it as a target.

In Swift 1.x, we just used a String and still had no compiler typo checking. In Swift 2.2, we have #selector (SE-0022) and we FINALLY have compiler type checking.

OSS FTW!!

ATTACH AN ACTION TO A UI ELEMENT

Page 30: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

TARGET-ACTION PATTERN IN SWIFT

17

Page 31: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

TARGET-ACTION PATTERN IN SWIFT

17

@objc func tappedButton(sender:UIButton!) { print("tapped button") }

Page 32: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

TARGET-ACTION PATTERN IN SWIFT

17

@objc func tappedButton(sender:UIButton!) { print("tapped button") } #if swift(>=2.2)

myButton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)

#else myButton.addTarget(self, action: "tappedButton",

forControlEvents: .TouchUpInside) #endif

Page 33: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

TARGET-ACTION PATTERN IN SWIFT

17

@objc func tappedButton(sender:UIButton!) { print("tapped button") } #if swift(>=2.2)

myButton.addTarget(self, action: #selector(tappedButton), forControlEvents: .TouchUpInside)

#else myButton.addTarget(self, action: "tappedButton",

forControlEvents: .TouchUpInside) #endif

1Legacy Objective-COnly @objc functions can be made #selectors

Page 34: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SINGLETON PATTERN

18

Fairly common in Cocoa, like [UIApplication sharedApplication]

In Swift, they’re much simpler to declare (and like ObjC, never dealloc’ed).

A static type property is guaranteed to be lazily initialized only once, even when accessed across multiple threads simultaneously.

SINGLETONS: GLOBAL SHARED INSTANCE

Page 35: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SINGLETON PATTERN IN SWIFT

19

class Singleton { static let sharedInstance = Singleton() }

Page 36: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SINGLETON PATTERN IN SWIFT

19

class Singleton { static let sharedInstance = Singleton() }

[]Well, That Was EasyObj-C is so much more complicated

[]Not All Shared Instances Are Singletonse.g. NSFileManager

Page 37: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

“INTROSPECTION PATTERN”

20

Apple’s Docs call this a pattern. It’s pretty much the same functionality as we discussed for Delegation. In my mind, “is this a kind of X class” and “does this implement Y method” are very limited forms of Introspection.

DYNAMICALLY EXAMINE TYPES AT RUNTIME

Page 38: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

“INTROSPECTION PATTERN”

20

Apple’s Docs call this a pattern. It’s pretty much the same functionality as we discussed for Delegation. In my mind, “is this a kind of X class” and “does this implement Y method” are very limited forms of Introspection.

DYNAMICALLY EXAMINE TYPES AT RUNTIME

[]Not Very UsefulWay harder in pure Swift than ObjC. Most attempts bridge NSObjects.

Page 39: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

API AVAILABILITY CHECKING “PATTERN”

21

Swift does this at Compile time rather than Runtime (like ObjC). Calling this a “Pattern” seems like a bit of a stretch to me, but Apple does. It is indisputably useful, though.

DECIDE WHETHER AN API IS AVAILABLE

Page 40: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

API AVAILABILITY CHECKING “PATTERN”

21

Swift does this at Compile time rather than Runtime (like ObjC). Calling this a “Pattern” seems like a bit of a stretch to me, but Apple does. It is indisputably useful, though.

DECIDE WHETHER AN API IS AVAILABLE

[]Also for Swift Version #sStarting with Swift 2.2

Page 41: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

API AVAILABILITY CHECKING “PATTERN” IN SWIFT

22

if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {

// Method is available for use. } else { // Method is not available. }

Page 42: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

API AVAILABILITY CHECKING “PATTERN” IN SWIFT

22

let locationManager = CLLocationManager() if #available(iOS 8.0, OSX 10.10, *) { locationManager.requestWhenInUseAuthorization() } let locationManager = CLLocationManager() guard #available(iOS 8.0, OSX 10.10, *) else { return } locationManager.requestWhenInUseAuthorization()

if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {

// Method is available for use. } else { // Method is not available. }

Page 43: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

API AVAILABILITY CHECKING “PATTERN” IN SWIFT

22

let locationManager = CLLocationManager() if #available(iOS 8.0, OSX 10.10, *) { locationManager.requestWhenInUseAuthorization() } let locationManager = CLLocationManager() guard #available(iOS 8.0, OSX 10.10, *) else { return } locationManager.requestWhenInUseAuthorization()

if ([CLLocationManager instancesRespondToSelector:@selector(requestWhenInUseAuthorization)]) {

// Method is available for use. } else { // Method is not available. }

#if swift(>=2.2) let tapped = #selector(tappedButton)

#endif

Page 44: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

VALUE TYPES/STRUCTS

23

Swift structs can have methods and implement protocols much like classes, but they’re always passed by value (copied) rather than passed by reference like objects (which makes them generally thread-safe, amongst other things).

SWIFT HAS RICH VALUE-TYPES

Page 45: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

UBIQUITOUS IMMUTABILITY

24

Pretty much all Swift variables can be declared immutable (with ‘let’), not just certain types like ObjC.

Immutable variables are safer, thread-safe and side-effect free, which is one claim to fame for functional languages.

NOT JUST FOR STRING/DICT/ARRAY ANYMORE

Page 46: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS

25

Swift has several mechanisms to keep error checking outside and separate from your business logic.

Checks often get moved from runtime to compile time, and syntax allows for checks to be isolated to avoid further complicating already-intricate code.

KEEP ERROR CHECKING AWAY FROM YOUR ALGORITHMS

Page 47: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS 1: if let

26

Much safer than finding out the hard way at runtime.

Unless you use (!)

You don’t use (!), do you? (At least not in shipping apps…)

ENFORCES NIL-CHECK AT COMPILE TIME

Page 48: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS IN SWIFT 1: if let

27

if let obj = obj { //business logic about object goes here }

Page 49: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS 2: guard

28

Good for checking at the top of a method

Avoids the “if-let pyramid of doom”

LIKE if-let, BUT WITH CONTINUING SCOPE

Page 50: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS IN SWIFT 2: guard

29

guard let obj = obj as? NSString where obj.length > 0 else { return }

//business logic about object goes here

Page 51: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS 3: defer

30

Make sure something happens as you exit a scope

SCHEDULE SOMETHING FOR LATER

Page 52: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS 3: defer

30

Make sure something happens as you exit a scope

SCHEDULE SOMETHING FOR LATER

[]Dearly Departed@synchronized(dict) { //use dict safely

}

Page 53: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS IN SWIFT 3: defer

31

let lock = NSLock()

func useLock() { lock.lock() defer { lock.unlock() } //use lock }

Page 54: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS: try?

32

The try syntax gets scattered all over your code.

Not exactly as good, but at least better than NSError** (or god forbid C’s return codes and errno).

TRY IS A COUNTER-EXAMPLE THOUGH

Page 55: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS IN SWIFT: try?

33

let url = try fileManager.URLForDirectory(.ApplicationDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)

try fileManager.removeItemAtURL( url.URLByAppendingPathComponent("/path/to/file", isDirectory: true))

if let path = url.URLByAppendingPathComponent("/path/to/file").path { let files = try fileManager.contentsOfDirectoryAtPath(path) //do something with files }

Page 56: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

SEPARATION OF ERRORS IN SWIFT: try?

33

let url = try fileManager.URLForDirectory(.ApplicationDirectory, inDomain: .UserDomainMask, appropriateForURL: nil, create: false)

try fileManager.removeItemAtURL( url.URLByAppendingPathComponent("/path/to/file", isDirectory: true))

if let path = url.URLByAppendingPathComponent("/path/to/file").path { let files = try fileManager.contentsOfDirectoryAtPath(path) //do something with files }

Page 57: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MONADS (A LA HASKELL MAYBE)

34

Very complicated, at least if you believe most people.

I remember being amazed - *Really amazed* at WWDC 2014 when I realized Apple stuck a Haskell Maybe Monad into Swift, and used all of 1-character to do it.

FUNCTIONAL PROGRAMMING CONCEPT

Page 58: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD

35

Page 59: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Page 60: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

Page 61: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

! ?

Page 62: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

! ?

?

Page 63: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

! ?

?

Page 64: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

! ?

?

!

Page 65: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

”MAYBE” MONAD SWIFT OPTIONAL

36

Optional

! ?

?

!

[]“!” Considered HARMFULI mean that in a “GOTO” sense.

Page 66: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE

37

Without this, the Internet as you know it would never have come to exist, and least not when and how it did.

SEMINAL PAPER BEHIND EARLY GOOGLE

http://static.googleusercontent.com/media/research.google.com/es/us/archive/mapreduce-osdi04.pdf

Page 67: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — MAP

38

Page 68: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — MAP

38

Page 69: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — MAP

38

[]

Rule of thumbSame count, Different Type

Page 70: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — MAP IN SWIFT

39

let names = ["RedStripeOnWhite.jpg","OrangeStripeOnWhite.jpg", "YellowStripeOnWhite.jpg","GreenStripeOnWhite.jpg", "BlackHorizontal.jpg","BlueStripeOnWhite.jpg", “IndigoStripeOnWhite.jpg”,"VioletStripeOnWhite.jpg"]

let images = names.map { UIImage(named: $0)

}

Page 71: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — MAP IN SWIFT

39

let names = ["RedStripeOnWhite.jpg","OrangeStripeOnWhite.jpg", "YellowStripeOnWhite.jpg","GreenStripeOnWhite.jpg", "BlackHorizontal.jpg","BlueStripeOnWhite.jpg", “IndigoStripeOnWhite.jpg”,"VioletStripeOnWhite.jpg"]

let images = names.map { UIImage(named: $0)

}

1Real WorlD: JSONI use this a lot to map JSON Dict to Object/Struct, but this is more visual

Page 72: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — FILTER

40

Page 73: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — FILTER

40

Page 74: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — FILTER

40

[]

Rule of thumbSame Type, Lower Count

Page 75: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — FILTER IN SWIFT

41

let colors = images.filter { !mono($0) }

Page 76: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — FILTER IN SWIFT

41

let colors = images.filter { !mono($0) }

1Real WorlD: JSONI use this a lot to throw out JSON Dicts I don’t need

Page 77: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

42

Page 78: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

42

Page 79: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

42

[]

Rule of thumbDifferent Type, Count == 1

Page 80: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

43

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 81: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

43

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 82: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

44

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 83: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

44

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 84: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

45

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 85: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

45

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 86: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

46

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 87: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

46

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 88: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

47

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 89: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

47

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 90: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

48

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 91: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

48

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 92: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

49

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 93: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE — REDUCE

49

let rainbowImage = ciImages.reduce(CIImage()) { (s, img) -> CIImage? in let f = CIFilter(name: "CISourceOverCompositing") f?.setValue(s, forKey: kCIInputBackgroundImageKey) f?.setValue(img, forKey:kCIInputImageKey) return f?.outputImage }

Page 94: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE - WAIT, WAIT, WAIT!!!

50

I have yet to see a case where map/reduce worked consistently faster on iOS than the equivalent for..in loop, and often it can be quite a bit slower.

BUT - learn it anyway.

ABOUT SWIFT’S MAPREDUCE PERFORMANCE…

Page 95: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

MAPREDUCE - SO WHAT’S THE POINT?

51

…or threads. Or at least, that was the design intent.

I still use it (although I don’t have to), because I’m used to it from other languages (and I use it with dispatch_groups, despite the fact they don’t fit on slides).

But Soon (SWIFT 4?? - see earlier email), we’ll have a Swift release that focuses on asynchronous functionality. And THEN, it will really, really matter.

MAPREDUCE SPLITS WORK BETWEEN MACHINES

Page 96: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PROTOCOL DEFAULT IMPLEMENTATIONS

52

Protocol Implementations allow for much more useful protocols, and for much more flexible implementations.

WHOLE NEW WORLD

Page 97: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PROTOCOL EXTENSIONS (W/IMPLEMENTATIONS)

53

Protocol Implementations allow for much more useful protocols, and for much more flexible implementations.

WHOLE NEW WORLD

Page 98: Swift 2.2 Design Patterns CocoaConf Austin 2016

Design Patterns in Swift 2.2CocoaConf Austin 2016

PROTOCOL EXTENSIONS (W/IMPLEMENTATIONS)

53

Protocol Implementations allow for much more useful protocols, and for much more flexible implementations.

WHOLE NEW WORLD

1Examples are ContrivedAnd they take a while to set up, and I’m expecting this is already going long

2Big TopicThere’s a whole (VERY GOOD) WWDC talk on just this.

Page 99: Swift 2.2 Design Patterns CocoaConf Austin 2016

Speaking to you all is always a pleasure.

Thank You

Page 100: Swift 2.2 Design Patterns CocoaConf Austin 2016

Speaking to you all is always a pleasure.

Thank You