Download - Cocoa Design Patterns in Swift

Transcript
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