Cocoa Design Patterns in Swift

106
Cocoa Design Patterns in Swift @MicheleTitolo

description

We have this new language, Swift, which takes some familiar Apple patterns, and introduces some new ones. With tools like closures and method chaining, there are definitely some new ways to solve the age-old Obj-c architecture challenges. This talk will walk through some of the most common Obj-c design patterns rewritten in Swift, and showcase the strengths and weaknesses of this new language.

Transcript of Cocoa Design Patterns in Swift

Page 1: Cocoa Design Patterns in Swift

Cocoa Design Patternsin Swift@MicheleTitolo

Page 2: Cocoa Design Patterns in Swift
Page 3: Cocoa Design Patterns in Swift
Page 4: Cocoa Design Patterns in Swift

• New language features

• Functional patterns

• Patterns in Swift

• Anti-patterns

What we’ll cover

Page 5: Cocoa Design Patterns in Swift

New language features

Page 6: Cocoa Design Patterns in Swift

Tuples

Page 7: Cocoa Design Patterns in Swift

Tuples group multiple values into a single compound value.

Page 8: Cocoa Design Patterns in Swift

let http404Error = (404, "Not Found")println(http404Error.0)

Page 9: Cocoa Design Patterns in Swift

var http200Response: (statusCode: Int, statusText: String, hasBody: Bool)

http200Response.statusCode = 200http200Response.statusText = "OK"http200Response.hasBody = true

Page 10: Cocoa Design Patterns in Swift

You can put any kind of object in a tuple

Page 11: Cocoa Design Patterns in Swift

Generics

Page 12: Cocoa Design Patterns in Swift

<T>

Page 13: Cocoa Design Patterns in Swift

More than just an id

Page 14: Cocoa Design Patterns in Swift

Abstraction

Page 15: Cocoa Design Patterns in Swift

Create functions without declaring type

Page 16: Cocoa Design Patterns in Swift

struct Stack<T> { var items = [T]() mutating func push(item: T) { items.append(item) } mutating func pop() -> T { return items.removeLast() }}

Page 17: Cocoa Design Patterns in Swift

<T: Equitable>

Page 18: Cocoa Design Patterns in Swift

AnyObject

Page 19: Cocoa Design Patterns in Swift

...used a lot more like id

Page 20: Cocoa Design Patterns in Swift

Closures

Page 21: Cocoa Design Patterns in Swift

“Closures are behaviors with attached state”

- Peter Norvig

Page 22: Cocoa Design Patterns in Swift

Like blocks, but better!

Page 23: Cocoa Design Patterns in Swift

var closure = { (params) -> returnType in statements}

Page 24: Cocoa Design Patterns in Swift

let

Page 25: Cocoa Design Patterns in Swift

Immutable variable

Page 26: Cocoa Design Patterns in Swift

var myString: String? = someFucntion()

if let greeting = myString { println(greeting)}else { println("Not a string") }

Page 27: Cocoa Design Patterns in Swift

Structs + Enums

Page 28: Cocoa Design Patterns in Swift

Structs:Pass-by-value

Page 29: Cocoa Design Patterns in Swift

struct Rect { var origin: Point var size: Size}

Page 30: Cocoa Design Patterns in Swift

Structs can have methods, and conform to protocols

Page 31: Cocoa Design Patterns in Swift

Enums:also pass-by-value

Page 32: Cocoa Design Patterns in Swift

Also can conform to protocols and have methods

Page 33: Cocoa Design Patterns in Swift

enum Rank: Int { case Ace = 1 case Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten case Jack, Queen, King func description() -> String { switch self { case .Ace: return "ace" case .Jack: return "jack" case .Queen: return "queen" case .King: return "king" default: return String(self.toRaw()) } }}

Page 34: Cocoa Design Patterns in Swift

Functional Patterns

Page 35: Cocoa Design Patterns in Swift

Function Passing

Page 36: Cocoa Design Patterns in Swift

func printExcitedly(string: String){ println(string + "!!!!!!!")}

var excitedFunc = printExcitedly

Page 37: Cocoa Design Patterns in Swift

Pass functions into functions

Page 38: Cocoa Design Patterns in Swift

func printVeryExcitedly(excitedFunction: (String) -> Void, message: String){

excitedFunction(message.uppercaseString)}

printVeryExcitedly(printExcitedly, "Hello");

Page 39: Cocoa Design Patterns in Swift

Return functions from functions

Page 40: Cocoa Design Patterns in Swift

func beExcited(excitementLevel: Int) -> (String) -> Void { ...}

Page 41: Cocoa Design Patterns in Swift

Patterns

Page 42: Cocoa Design Patterns in Swift

Composition

Page 43: Cocoa Design Patterns in Swift

...because we can pass functions!

Page 44: Cocoa Design Patterns in Swift

The OO way

Page 45: Cocoa Design Patterns in Swift

class Car { let numWheels: Int let numCylinders: Int init (numWheels: Int, numCylinders: Int) { self.numWheels = numWheels self.numCylinders = numCylinders }}

var newCar = Car(numWheels: 4,numCylinders: 4)var otherCar = Car(numWheels: 4, numCylinders: 6)

Page 46: Cocoa Design Patterns in Swift

var motorcycle = ??

Page 47: Cocoa Design Patterns in Swift

class Motorcycle { ...}

Page 48: Cocoa Design Patterns in Swift

This is not ideal

Page 49: Cocoa Design Patterns in Swift

protocol Vehicle { var numWheels: Int {get set} var numCylinders: Int {get set} func drive()}

Page 50: Cocoa Design Patterns in Swift

Better

Page 51: Cocoa Design Patterns in Swift

How do we handle this at scale?

Page 52: Cocoa Design Patterns in Swift
Page 53: Cocoa Design Patterns in Swift
Page 54: Cocoa Design Patterns in Swift

struct WheelSet { var wheelSize: Int var wheelFrictionCoefficient: Float}

struct BodyType { var numWheels: Int var wheels: WheelSet var wheelBase: Float}

enum EngineType: Int { case Automatic, Manual}

protocol Vehicle { var body: BodyType {get set} var transmission: EngineType {get set} func drive(force: Float) func turn(speed: Float)}

Page 55: Cocoa Design Patterns in Swift

Better

Page 56: Cocoa Design Patterns in Swift

...but we can still improve

Page 57: Cocoa Design Patterns in Swift

Factories

Page 58: Cocoa Design Patterns in Swift

Abstract away objectcreation and composition

Page 59: Cocoa Design Patterns in Swift

protocol VehicleCreator { func createVehicle(bodyType: BodyType, engineType: EngineType) -> Vehicle}

class VehicleFactory: VehicleCreator { func createVehicle(bodyType: BodyType, engineType: EngineType) -> Vehicle {}}

Page 60: Cocoa Design Patterns in Swift

protocol VehicleCreator { func createVehicle(bodyType: BodyType, engineType: EngineType) -> Vehicle}

class VehicleFactory: VehicleCreator { func createVehicle(bodyType: BodyType, engineType: EngineType) -> Vehicle {}}

class MotorcycleFactory: VehicleCreator { func createVehicle(bodyType: BodyType, engineType: EngineType) -> Vehicle {}}

Page 61: Cocoa Design Patterns in Swift

This still looks very OO

Page 62: Cocoa Design Patterns in Swift

class VehicleFactory { func wheelSetGenerator(wheelSize: Int, friction: Float) -> WheelSet { return WheelSet(wheelSize: wheelSize, wheelFrictionCoefficient: friction) } func generateBodyType(wheelCount: Int, wheelType: WheelSet, wheelBase: Float) -> (Void) -> BodyType { func bodyGen() -> BodyType { return BodyType(numWheels:wheelCount, wheels:wheelType, wheelBase:wheelBase) } return bodyGen } func createVehicle( bodyGenerator:(wheelCount: Int, wheelType: WheelSet, wheelBase: Float) -> BodyType, transmission: EngineType) -> Vehicle {}}

Page 63: Cocoa Design Patterns in Swift

let factory: VehicleFactory = VehicleFactory()let motorcycleWheelSet: WheelSet = factory.wheelSetGenerator(28, friction: 0.5)let motorcycleBodyGen = factory.generateBodyType(2, wheelType:motorcycleWheelSet, wheelBase: 45)let motorcycle = factory.createVehicle(motorcycleBodyGen, transmission: .Manual)let electricMotorcycle = factory.createVehicle(motorcycleBodyGen, transmission: .Auomatic)

Page 64: Cocoa Design Patterns in Swift

Factories in Swift can be incredibly flexible

Page 65: Cocoa Design Patterns in Swift

Command

Page 66: Cocoa Design Patterns in Swift

A delegate chainthat returns a function

Page 67: Cocoa Design Patterns in Swift

protocol Commander { func commandSomething(String) -> (Int) -> Dictionary<String, String>}

class ViewController: { let delegate: Commander}

Page 68: Cocoa Design Patterns in Swift

Why is this better than closures?

Page 69: Cocoa Design Patterns in Swift

It’s more explicit

Page 70: Cocoa Design Patterns in Swift

It’s more flexible

Page 71: Cocoa Design Patterns in Swift

Enumeration

Page 72: Cocoa Design Patterns in Swift

Not the type enum!

Page 73: Cocoa Design Patterns in Swift

We have new ways of transforming collections

Page 74: Cocoa Design Patterns in Swift

[1,2,3,4].map { (var number) -> Int in return number * number}

Page 75: Cocoa Design Patterns in Swift

var array = [3, 2, 5, 1, 4]array.sort { $0 < $1 }

Page 76: Cocoa Design Patterns in Swift

let array = [1, 2, 3, 4, 5]let reversedArray = array.reverse()// reversedArray = [5, 4, 3, 2, 1]

Page 77: Cocoa Design Patterns in Swift

And of course, this is useful for more than just math

Page 78: Cocoa Design Patterns in Swift

var vehicles = [suv, motorcycle, electricMotorcycle, car, truck]var manualVehicles = vehicles.filter { (var vehicle: Vehicle) -> Vehicle in return (vehicle.transmission == .Manual) }// manualVehicles = [motorcycle, truck]

Page 79: Cocoa Design Patterns in Swift

Encapsulate better

Page 80: Cocoa Design Patterns in Swift

func meanMedianMode(a: Array<Int>) -> (mean:Int, median:Int, mode:Int) { var mean = findMean(a) var median = findMedian(a) var mode = findMode(a) return (mean, median, mode)}

Page 81: Cocoa Design Patterns in Swift

Tuples with names are incredibly useful

Page 82: Cocoa Design Patterns in Swift

Anti-Patterns

Page 83: Cocoa Design Patterns in Swift

No changes to handling protocols

Page 84: Cocoa Design Patterns in Swift

This is the slide I was hoping to put something magical on

Page 85: Cocoa Design Patterns in Swift

class ViewController: UIViewController, UITableViewDataSource { var tableView: UITableView func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! { var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as UITableViewCell if (cell == nil) { cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell") } cell.textLabel.text = "Hello World" return cell } func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int { return 1 }}

Page 86: Cocoa Design Patterns in Swift

Protocols are first class citizens in Swift, just like in Obj-c

Page 87: Cocoa Design Patterns in Swift

Tuples all the way down

Page 88: Cocoa Design Patterns in Swift
Page 89: Cocoa Design Patterns in Swift

Yes, you can put a tuple in a tuple

Page 90: Cocoa Design Patterns in Swift

These are temporary data structures

Page 91: Cocoa Design Patterns in Swift

We have better OO tools available

Page 92: Cocoa Design Patterns in Swift

Operator overloading

Page 93: Cocoa Design Patterns in Swift

Don’t overload default operators

Page 94: Cocoa Design Patterns in Swift

func decode(json: JSON) -> User? { return _JSONObject(json) >>> { d in User.create <^> d["id"] >>> _JSONInt <*> d["name"] >>> _JSONString <*> d["email"] >>> _JSONString }}

Page 95: Cocoa Design Patterns in Swift

Operators make code harder to read

Page 96: Cocoa Design Patterns in Swift

Type is still important

Page 97: Cocoa Design Patterns in Swift

Getting classes from AnyObject are kind of a pain

Page 98: Cocoa Design Patterns in Swift
Page 99: Cocoa Design Patterns in Swift

Still be explicit when you can

Page 100: Cocoa Design Patterns in Swift

var music: [String: String] = ["AC/DC": "Hells Bells", "Red Hot Chili Peppers": "Californication"]

Page 101: Cocoa Design Patterns in Swift

In Summary

Page 102: Cocoa Design Patterns in Swift

Swift gives us new tools

Page 103: Cocoa Design Patterns in Swift

But Objective-C, and its patterns, aren’t going away

anytime soon

Page 104: Cocoa Design Patterns in Swift

• Today 11:30amInteroperating Swift with Lower Level Code by Stephan Tramer in Terrace

• Tomorrow 1:45pm Functional Programming in Swift by Chris Eidhof in Vail

More Swift!

Page 105: Cocoa Design Patterns in Swift

• Swift Programming Guide from Apple

• Design Patterns in Dynamic Programming by Peter Norvig

• Erica Sadun’s many blog posts on Swift

• Functional Programming in Swift, ebook by Objc.io founders (See Chris’ talk tomorrow!)

• Instance Methods and Curried Functions in Swift by Ole Begemann

Resources

Page 106: Cocoa Design Patterns in Swift

Thanks!@MicheleTitolo