Talk on Swift 2.2, adapting Cocoa/Objective-C Design Patterns to Swift, Design Patterns from other Languages that Swift has adopted, and Swift features that lend themselves to new Design Patterns.
08448380779 Call Girls In Diplomatic Enclave Women Seeking Men
Swift 2.2 Design Patterns CocoaConf Austin 2016
1. 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
2. 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
5. These mean a lot of different things to
different people.
Hopefully they’re of some use to you.
WIDELY RECOGNIZED,
BUT NOT UNDISPUTED
6. 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?
7. 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?
8. 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?
9. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
10. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
Classic Cocoa Design Patterns as
implemented in Swift
11. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
Classic Cocoa Design Patterns as
implemented in Swift
Some Gang of Four Patterns that lend
themselves to Swift
12. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
Classic Cocoa Design Patterns as
implemented in Swift
Some Gang of Four Patterns that lend
themselves to Swift
Patterns Apple Documents for Swift
13. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
Classic Cocoa Design Patterns as
implemented in Swift
Some Gang of Four Patterns that lend
themselves to Swift
Patterns Apple Documents for Swift
Patterns from Other Languages
14. Design Patterns in Swift 2.2CocoaConf Austin 2016
PATTERN SOURCES FOR TODAY
8
Classic Cocoa Design Patterns as
implemented in Swift
Some Gang of Four Patterns that lend
themselves to Swift
Patterns Apple Documents for Swift
Patterns from Other Languages
Interesting/Potential Swift-specific Patterns
15.
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
16.
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 Construction
This is a big reason why we don’t have
to use the “Factory Pattern” in Cocoa/
Swift
17. 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)
18. 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)
1
Test Delegate Optional
The delegate itself must
not be nil (check with ?
and don’t (EVER) use !)
2
Test Method Exists
Put ? after method call to
test for @optional
implementation
19.
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**)
20.
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 Throw
try on each line that might
throw
catch for blocks
21. 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);
}
}
22. 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);
}
}
23.
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
24. Design Patterns in Swift 2.2CocoaConf Austin 2016
OBSERVER PATTERN IN SWIFT
14
25. Design Patterns in Swift 2.2CocoaConf Austin 2016
OBSERVER PATTERN IN SWIFT
14
objectToObserve.addObserver(self, forKeyPath: "myDate", options: .New,
context: &myContext)
26. 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)
}
}
27. 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)
28. Design Patterns in Swift 2.2CocoaConf Austin 2016
SWIFT-NATIVE KVO *MAYBE* IN SWIFT 4
15
29.
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
30. Design Patterns in Swift 2.2CocoaConf Austin 2016
TARGET-ACTION PATTERN IN SWIFT
17
31. Design Patterns in Swift 2.2CocoaConf Austin 2016
TARGET-ACTION PATTERN IN SWIFT
17
@objc func tappedButton(sender:UIButton!) {
print("tapped button")
}
32. 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
33. 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
1
Legacy Objective-C
Only @objc functions can
be made #selectors
34.
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
35. Design Patterns in Swift 2.2CocoaConf Austin 2016
SINGLETON PATTERN IN SWIFT
19
class Singleton {
static let sharedInstance = Singleton()
}
36. Design Patterns in Swift 2.2CocoaConf Austin 2016
SINGLETON PATTERN IN SWIFT
19
class Singleton {
static let sharedInstance = Singleton()
}
[]
Well, That Was Easy
Obj-C is so much more
complicated
[]
Not All Shared Instances Are Singletons
e.g. NSFileManager
37.
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
38.
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 Useful
Way harder in pure Swift
than ObjC. Most attempts
bridge NSObjects.
39.
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
40.
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 #s
Starting with Swift 2.2
41. 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.
}
42. 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.
}
43. 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
44.
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
45.
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
46.
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
47.
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
48. 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
}
49.
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
50. 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
51.
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
52.
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
}
53. 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
}
54.
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
55. 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
}
56. 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
}
57.
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
59. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
60. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
61. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
! ?
62. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
! ?
?
63. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
! ?
?
64. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
! ?
?
!
65. Design Patterns in Swift 2.2CocoaConf Austin 2016
”MAYBE” MONAD SWIFT OPTIONAL
36
Optional
! ?
?
!
[]
“!” Considered HARMFUL
I mean that in a “GOTO” sense.
66.
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
69.
Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — MAP
38
[]
Rule of thumb
Same count,
Different Type
70. 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)
}
71. 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)
}
1
Real WorlD: JSON
I use this a lot to map
JSON Dict to Object/Struct,
but this is more visual
72. Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — FILTER
40
74. Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — FILTER
40
[]
Rule of thumb
Same Type,
Lower Count
75. Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — FILTER IN SWIFT
41
let colors = images.filter { !mono($0) }
76. Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — FILTER IN SWIFT
41
let colors = images.filter { !mono($0) }
1
Real WorlD: JSON
I use this a lot to throw out
JSON Dicts I don’t need
77. Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — REDUCE
42
78.
Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — REDUCE
42
79.
Design Patterns in Swift 2.2CocoaConf Austin 2016
MAPREDUCE — REDUCE
42
[]
Rule of thumb
Different Type,
Count == 1
80. 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
}
81. 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
}
82. 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
}
83. 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
}
84. 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
}
85. 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
}
86. 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
}
87. 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
}
88. 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
}
89. 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
}
90. 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
}
91. 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
}
92. 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
}
93. 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
}
94.
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…
95.
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
96.
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
97.
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
98.
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
1
Examples are Contrived
And they take a while to
set up, and I’m expecting
this is already going long
2
Big Topic
There’s a whole (VERY
GOOD) WWDC talk on just
this.