Slide 1

Slide 1 text

Dan Cutting @dcutting cutting.io Swifty?

Slide 2

Slide 2 text

Singletons! 503,000 359,000 "swift singleton" "swift singleton bad"

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

var report = getSpyReport() report = encrypt(message: report) transmit(message: report) !

Slide 5

Slide 5 text

var report = getSpyReport() //report = encrypt(message: report) transmit(message: report) !

Slide 6

Slide 6 text

enum Encrypted {} // Phantom types! enum Decrypted {} func transmit(message: Secret) { // ... } struct Secret { let value: String }

Slide 7

Slide 7 text

Cannot convert value of type 'Secret' to expected argument type 'Secret' func getSpyReport() -> Secret { return Secret(value: "!") } let report = getSpyReport() transmit(message: report)

Slide 8

Slide 8 text

func encrypt(message: Secret) -> Secret { let encrypted = rot13(message: message.value) return Secret(value: encrypted) } let report = getSpyReport() let encrypted = encrypt(message: report) transmit(message: encrypted)

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

struct Array { // ... }

Slide 11

Slide 11 text

class Warren { enum Mick { struct Jim { static let rock = true } } } Warren.Mick.Jim.rock

Slide 12

Slide 12 text

struct Array { // ... }

Slide 13

Slide 13 text

enum MyProject { struct Array { // ... } } let myArray = MyProject.Array()

Slide 14

Slide 14 text

enum Components { enum List {} enum Search {} enum Detail {} } extension Components.List { class Service { // ... } } let listService = Components.List.Service()

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

Building blocks that add behaviour to types

Slide 17

Slide 17 text

mixin CanMove { var position = CGPoint.zero var speed = CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } } struct Player: CanMove, HasHealth {} struct Enemy: CanMove, HasMagic {}

Slide 18

Slide 18 text

struct CanMoveMixin { var position = CGPoint.zero var speed = CGVector.zero mutating func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } } mixin CanMove { var position = CGPoint.zero var speed = CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } }

Slide 19

Slide 19 text

protocol CanMove { mutating func move(for timeSlice: CGFloat) } mixin CanMove { var position = CGPoint.zero var speed = CGVector.zero func move(for timeSlice: CGFloat) { position = position + timeSlice * speed } }

Slide 20

Slide 20 text

struct Player: CanMove { var canMoveMixin = CanMoveMixin() mutating func move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }

Slide 21

Slide 21 text

struct Enemy: CanMove { var canMoveMixin = CanMoveMixin() mutating func move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }

Slide 22

Slide 22 text

protocol CanMove { mutating func move(for timeSlice: CGFloat) } var canMoveMixin: CanMoveMixin { get set } extension CanMove { mutating func move(for timeSlice: CGFloat) { canMoveMixin.move(for: timeSlice) } }

Slide 23

Slide 23 text

struct Player: CanMove, HasHealth { var canMoveMixin = CanMoveMixin() var hasHealthMixin = HasHealthMixin() } struct Enemy: CanMove, HasMagic { var canMoveMixin = CanMoveMixin() var hasMagicMixin = HasMagicMixin() } struct Player: CanMove, HasHealth {} struct Enemy: CanMove, HasMagic {}

Slide 24

Slide 24 text

swift

Slide 25

Slide 25 text

is wtf?

Slide 26

Slide 26 text

• SE-0007: Remove C-style for-loops with conditions and incrementers • SE-0016: Adding initializers to Int and UInt to convert from UnsafePointer and UnsafeMutablePointer • SE-0019: Swift Testing • SE-0023: API Design Guidelines • SE-0028: Modernizing Swift's Debugging Identifiers (__FILE__, etc) • SE-0029: Remove implicit tuple splat behavior from function applications • SE-0031: Adjusting inout Declarations for Type Decoration • SE-0034: Disambiguating Line Control Statements from Debugging Identifiers • SE-0037: Clarify interaction between comments & operators • SE-0039: Modernizing Playground Literals • SE-0040: Replacing Equal Signs with Colons For Attribute Arguments • SE-0043: Declare variables in 'case' labels with multiple patterns • SE-0046: Establish consistent label behavior across all parameters including first labels • SE-0049: Move @noescape and @autoclosure to be type attributes • SE-0053: Remove explicit use of let from Function Parameters • SE-0054: Abolish ImplicitlyUnwrappedOptional type • SE-0055: Make unsafe pointer nullability explicit using Optional • SE-0059: Update API Naming Guidelines and Rewrite Set APIs Accordingly • SE-0061: Add Generic Result and Error Handling to autoreleasepool() • SE-0065: A New Model For Collections and Indices • SE-0069: Mutability and Foundation Value Types • SE-0070: Make Optional Requirements Objective-C-only • SE-0071: Allow (most) keywords in member references • SE-0072: Fully eliminate implicit bridging conversions from Swift • SE-0025: Scoped Access Level • SE-0032: Add find method to SequenceType • SE-0033: Import Objective-C Constants as Swift Types • SE-0035: Limiting inout capture to @noescape contexts • SE-0036: Requiring Leading Dot Prefixes for Enum Instance Member Impleme • SE-0038: Package Manager C Language Target Support • SE-0042: Flattening the function type of unapplied method references • SE-0044: Import as Member • SE-0045: Add scan, prefix(while:), drop(while:), and iterate to the stdlib • SE-0047: Defaulting non-Void functions so they warn on unused results • SE-0048: Generic Type Aliases • SE-0052: Change IteratorType post-nil guarantee • SE-0057: Importing Objective-C Lightweight Generics • SE-0062: Referencing Objective-C key-paths • SE-0063: SwiftPM System Module Search Paths • SE-0064: Referencing the Objective-C selector of property getters and setters • SE-0066: Standardize function type argument syntax to require parentheses • SE-0067: Enhanced Floating Point Protocols • SE-0068: Expanding Swift Self to class members and value types

Slide 27

Slide 27 text

let var

Slide 28

Slide 28 text

var url = NSURL(fileURLWithPath: "/dev") url = url.URLByAppendingPathComponent("/null")

Slide 29

Slide 29 text

var url = URL(fileURLWithPath: "/dev") try! url.appendPathComponent("/null")

Slide 30

Slide 30 text

let url = URL(fileURLWithPath: "/dev") try! url.appendPathComponent("/null")

Slide 31

Slide 31 text

public class Counter { private var value: Int = 0 public func increment() { value += 1 } } let counter = Counter() counter.increment() counter.value = 99 Scoped Access

Slide 32

Slide 32 text

func apply(value: Int, f: @noescape (Int) -> (Int)) -> Int { return f(value) }. let _ = apply(value: 7) { $0 * 2 }. @noescape

Slide 33

Slide 33 text

func apply(value: Int, f: (Int) -> (Int)) -> Int { return f(value) }. let _ = apply(value: 7) { $0 * 2 }. @noescape

Slide 34

Slide 34 text

protocol Drama {} protocol Comedy {} struct BreakfastClub: Drama, Comedy {} let movie: Drama & Comedy = BreakfastClub() let movie: protocol = BreakfastClub() func watch(dramedy: T) { // ... } Protocols

Slide 35

Slide 35 text

for loops! for (var i = 0; i < 10; i++) { print(i) } for i in (0..<10) { print(i) }

Slide 36

Slide 36 text

for x in sequence(first: 1, next: { $0 * 2 }) { print(x) } .prefix(4)

Slide 37

Slide 37 text

struct Fib { var current: Int var next: Int } let f = Fib(current: 0, next: 1) let s = sequence(state: f) { (f: inout Fib) -> Int? in return f.current } defer { } let sum = f.current + f.next f.current = f.next f.next = sum

Slide 38

Slide 38 text

@dcutting