├── .gitignore ├── LICENSE ├── README.md ├── The Swift Summary Book.playground ├── Pages │ ├── 01 The Basics.xcplaygroundpage │ │ └── Contents.swift │ ├── 02 Basic Operators.xcplaygroundpage │ │ └── Contents.swift │ ├── 04 Collection Types.xcplaygroundpage │ │ └── Contents.swift │ ├── 05 Control Flow.xcplaygroundpage │ │ └── Contents.swift │ ├── 06 Functions.xcplaygroundpage │ │ └── Contents.swift │ ├── 07 Closures.xcplaygroundpage │ │ └── Contents.swift │ ├── 08 Enumerations.xcplaygroundpage │ │ └── Contents.swift │ ├── 09 Classes & Structs.xcplaygroundpage │ │ └── Contents.swift │ ├── 10 Properties.xcplaygroundpage │ │ └── Contents.swift │ ├── 11 Methods.xcplaygroundpage │ │ └── Contents.swift │ ├── 12 Subscripts.xcplaygroundpage │ │ └── Contents.swift │ ├── 13 Inheritance.xcplaygroundpage │ │ └── Contents.swift │ ├── 14 Initialization.xcplaygroundpage │ │ └── Contents.swift │ ├── 15 Deinitialization.xcplaygroundpage │ │ └── Contents.swift │ ├── 16 ARC.xcplaygroundpage │ │ └── Contents.swift │ ├── 17 Optional Chaining.xcplaygroundpage │ │ └── Contents.swift │ ├── 18 Error Handling.xcplaygroundpage │ │ └── Contents.swift │ ├── 19 Type Casting.xcplaygroundpage │ │ └── Contents.swift │ ├── 21 Extensions.xcplaygroundpage │ │ └── Contents.swift │ ├── 22 Protocols.xcplaygroundpage │ │ └── Contents.swift │ ├── 23 Generics.xcplaygroundpage │ │ └── Contents.swift │ └── 24 Access Control.xcplaygroundpage │ │ └── Contents.swift ├── Resources │ ├── Higher Order Functions.playground │ │ ├── Contents.swift │ │ └── contents.xcplayground │ └── LICENSE └── contents.xcplayground └── swift_brand_logo.svg /.gitignore: -------------------------------------------------------------------------------- 1 | ## Playgrounds 2 | timeline.xctimeline 3 | playground.xcworkspace 4 | .DS_Store 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Juan Antonio Karmy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Platform](https://img.shields.io/badge/platform-osx-lightgrey.svg) 3 | ![Swift](https://img.shields.io/badge/swift-v3.0-orange.svg) ![Software](https://img.shields.io/badge/software-Xcode%20%7C%20Playgrounds-blue.svg) 4 | # The Swift Summary Book 5 | A summary of Apple's Swift language written on Playgrounds. 6 | 7 | ### Why this summary? 8 | Apple's documentation is great for learning Swift, but who's got the time to read all that? :smile: 9 | 10 | This summary cuts to the chase. It is directly written on the Playgrounds platform, which makes it very interactive. 11 | You can tinker around with it as much as you like! 12 | 13 | ## Inside the Box 14 | Once you've downloaded or cloned the repository and you open it with Xcode, you'll find most of the chapters from Apple's documentation, plus a *Resources* folder that contains extra material. The numbering in each chapter is consistent with Apple's. Chapters with a ~~strikethrough~~ have not been added to the book yet as being considered *unimportant*. More specifically, you'll find: 15 | 16 | **Chapters** 17 | 18 | 01. The Basics 19 | 02. Basic Operators 20 | 03. ~~Strings and Characters~~ 21 | 04. Collection Types 22 | 05. Control Flow 23 | 06. Functions 24 | 07. Closures 25 | 08. Enumerations 26 | 09. Classes & Structs 27 | 10. Properties 28 | 11. Methods 29 | 12. Subscripts 30 | 13. Inheritance 31 | 14. Initialization 32 | 15. Deinitialization 33 | 16. ARC 34 | 17. Optional Chaining 35 | 18. Error Handling 36 | 19. Type Casting 37 | 20. ~~Nested Types~~ 38 | 21. Extensions 39 | 22. Protocols 40 | 23. Generics 41 | 24. Access Control 42 | 43 | **Resources** 44 | - Higher Order Functions 45 | 46 | ## How should I install this? 47 | Getting started with The Swift Summary Book is a piece of 🎂: 48 | 49 | 1. Just clone or download the repository. 50 | 2. You need to have Xcode v8.0 or above. You can download it [here](https://developer.apple.com/xcode/). 51 | 3. Open the `.swift` file with Xcode and *voilà*! 52 | 53 | ## What are the features? 54 | The Swift Summary Book takes advantage of the Playground platform and many of its powerful capabilities: 55 | * The book is made of a single file that contains all chapters inside, which allows for easy access. 56 | * Chapters use the Playground Markup Language, which brings rich documentation to the code examples. 57 | * Every chapter has Page Linking, which allows to go back and forth from one chapter to the next, previous or another that was mentioned with in the chapter. 58 | 59 | 60 | ## Keep in mind 61 | The Swift language is still under rapid development, which means that the documentation is changing all the time, and some sections might break at a given time. 62 | 63 | 64 | ## You can help too! 65 | * Help me keep this summary :+1: by creating pull requests and issues! 66 | * Share this project and make sure you and others give it a ⭐ 67 | 68 | 69 | ## You can find me on 70 | * 🐦 twitter: [@jkarmy](http://twitter.com/jkarmy). 71 | * ☕️ If you like the open-source work I do, consider [buying me a coffee](https://www.buymeacoffee.com/juankarmy) so I can stay awake and keep typing away! 72 | 73 | ## License 74 | The MIT License (MIT) 75 | 76 | Copyright (c) 2016 Juan Antonio Karmy 77 | 78 | Permission is hereby granted, free of charge, to any person obtaining a copy 79 | of this software and associated documentation files (the "Software"), to deal 80 | in the Software without restriction, including without limitation the rights 81 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 82 | copies of the Software, and to permit persons to whom the Software is 83 | furnished to do so, subject to the following conditions: 84 | 85 | The above copyright notice and this permission notice shall be included in all 86 | copies or substantial portions of the Software. 87 | 88 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 89 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 90 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 91 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 92 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 93 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 94 | SOFTWARE. 95 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/01 The Basics.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | [Previous](@previous) | [Next](@next) 3 | **** 4 | 5 | Copyright (c) 2016 Juan Antonio Karmy. 6 | Licensed under MIT License 7 | 8 | Official Apple documentation available at [Swift Language Reference](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/) 9 | 10 | See Juan Antonio Karmy - [karmy.co](http://karmy.co) | [@jkarmy](http://twitter.com/jkarmy) 11 | 12 | **** 13 | */ 14 | 15 | /*: 16 | # THE BASICS 17 | */ 18 | 19 | import UIKit 20 | 21 | var str = "Hello, playground" 22 | let hello = "Hola, qué tal" 23 | 24 | 25 | /*: Optionals can be nil or the number they store, if any. */ 26 | var optionalInteger: Int? 27 | optionalInteger = 42 28 | 29 | 30 | 31 | /*: Reserved words can be used as variables or constants using `` */ 32 | let `private` = "private word" 33 | var word = `private` 34 | 35 | 36 | /*: Printing strings can be achieved by "sum" or by ```` \() ```` */ 37 | print(hello + " " + word) 38 | print("\(hello) \(word)") 39 | 40 | 41 | /*: Padding numbers with "_" makes them more readable */ 42 | var paddedInteger = 1_000_000 43 | 44 | 45 | /*: 46 | Explicit conversion must be made when working with explicit types. 47 | For any other case, use the Int class 48 | */ 49 | let thousand: UInt16 = 1_000 50 | let one: UInt8 = 1 51 | let thousandAndOne = thousand + UInt16(one) 52 | 53 | 54 | /*:Inferred as Int by default */ 55 | let anotherNumber: Int = Int(UINT32_MAX) 56 | let number = 6745 57 | let result = anotherNumber + number 58 | 59 | 60 | /*: ````typealias```` is a convenient way to refer to another type in a contextual way. */ 61 | typealias AudioResolution = UInt16 62 | AudioResolution.min 63 | 64 | /*: Tuples can be of any kind and of any number of elements */ 65 | let success = (200, "Success") 66 | typealias Success = (Int, String) 67 | let exito: Success = success 68 | 69 | /*: 70 | If you receive a response in this format, it can be conveniently stored like this. 71 | */ 72 | let (code, message) = success 73 | 74 | /*: If you just need one value. */ 75 | let (response, _) = success 76 | 77 | /*: Values can be accessed like indexes */ 78 | success.0 79 | success.1 80 | 81 | /*: Or, names can be added upon declaration */ 82 | let someTuple = (number: 456, assertion: "Yes") 83 | someTuple.number 84 | someTuple.assertion 85 | 86 | 87 | /*: Optionals may have a value or not. */ 88 | let optional: Int? = 2 89 | 90 | if optional != nil { 91 | "It's not nil!" 92 | optional! 93 | } else { 94 | "It's nil" 95 | } 96 | 97 | /*: You can use optional binding to test for an unassigned value as well */ 98 | 99 | if let value = optional { 100 | "It's not nil!" 101 | value 102 | }else { 103 | "It's nil" 104 | } 105 | 106 | /*: 107 | You can also use implicitly unwrapped optionals. Value becomes accessible automatically once a value has been set 108 | */ 109 | 110 | let knownString: Int! = 10 111 | if knownString != nil { 112 | "It's got a value" 113 | knownString // No need for explicit unwrapping 114 | } 115 | 116 | assert(true == true, "True isn't equal to false") 117 | 118 | /*: 119 | **** 120 | [Previous](@previous) | [Next](@next) 121 | */ 122 | 123 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/02 Basic Operators.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | //BASIC OPERATORS 14 | 15 | // Playground - noun: a place where people can play 16 | 17 | import UIKit 18 | 19 | let (x, y) = (1, 2) 20 | 21 | //Addition is also available for strings 22 | let string = "hello, " + "world" 23 | 24 | //Nil Coalescing Operator 25 | //It's equivalent to (a ? b : c), but for optionals 26 | 27 | var optional: String? //Currently nil 28 | 29 | // optional = "Some Value" // Uncomment/comment this line and observe what values get printed below 30 | var value = optional ?? "Value when `optional` is nil" 31 | 32 | // above statement is equivalent to below 33 | // if optional != nil { 34 | // value = optional! //Unwrapped value 35 | // } else { 36 | // value = "Value when `optional` is nil" 37 | // } 38 | 39 | //Range operators 40 | for index in 1...5 { 41 | //It will iterate 5 times. 42 | } 43 | 44 | var array = [1,2,3] 45 | 46 | for index in 0.. String{ 13 | return "Hello \(personName)!" 14 | } 15 | 16 | //In this case we return a tuple 17 | func minMax(array: [Int]) -> (min: Int, max:Int)? { 18 | if array.isEmpty {return nil} 19 | return (0,1) 20 | } 21 | 22 | //Note: returning void translates in returning an empty tuple: () 23 | 24 | //Here we are using external and local params names. 25 | //Also, note how the last param is predefined. This means we can omit it when calling the function. 26 | //Also note that an external name will be provided automatically to every predefined param. 27 | func join(string s1: String, toString s2: String, withJoiner joiner: String = " ") 28 | -> String { 29 | return s1 + joiner + s2 30 | } 31 | 32 | //A variadic param can take more than one value of a specified type. 33 | func arithmeticMean(numbers: Double...) -> Double { 34 | var total: Double = 0 35 | for number in numbers { 36 | total += number 37 | } 38 | return total / Double(numbers.count) 39 | } 40 | 41 | //In this example, the inout prefix defines that the passed parameters' values can be modified, 42 | //and this will be reflected on the original variables defined outside of the function. 43 | func swapTwoInts( a: inout Int, b: inout Int) { 44 | let temporaryA = a 45 | a = b 46 | b = temporaryA 47 | } 48 | 49 | //You can use a function type to pass functions as params to other functions. 50 | func printMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) { 51 | print("Result: \(mathFunction(a, b))") 52 | } 53 | 54 | //You can use function type to return functions. 55 | //Here, we are also defining nested functions. These functions can only be accessed through the parent function. 56 | //but can be passed as return values. 57 | func chooseStepFunction(backwards: Bool) -> (Int) -> Int { 58 | func stepForward(input: Int) -> Int { return input + 1 } 59 | func stepBackward(input: Int) -> Int { return input - 1 } 60 | return backwards ? stepBackward : stepForward 61 | } 62 | 63 | 64 | //Start 65 | sayHello(personName: "Juan") 66 | 67 | minMax(array: []) 68 | 69 | join(string: "Hello", toString: "World", withJoiner: "New") 70 | join(string: "", toString: "") 71 | 72 | arithmeticMean(numbers: 4,5,6,7) 73 | 74 | var someInt = 3 75 | var anotherInt = 107 76 | swapTwoInts(a: &someInt, b: &anotherInt) 77 | 78 | //Here we are defining a var of type function. 79 | var mathFunction: (String) -> String = sayHello 80 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/07 Closures.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | /*: 2 | [Previous](@previous) | [Next](@next) 3 | **** 4 | 5 | Copyright (c) 2016 Juan Antonio Karmy. 6 | Licensed under MIT License 7 | 8 | Official Apple documentation available at [Swift Language Reference](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/) 9 | 10 | See Juan Antonio Karmy - [karmy.co](http://karmy.co) | [@jkarmy](http://twitter.com/jkarmy) 11 | 12 | **** 13 | */ 14 | 15 | /*: 16 | # CLOSURES 17 | */ 18 | 19 | 20 | /*: 21 | ## INLINE CLOSURES 22 | */ 23 | 24 | var array = ["John", "Tim", "Steve"] 25 | 26 | var reversed = array.sorted(by: {(s1: String, s2: String) -> Bool in return s1 > s2}) 27 | 28 | //: Using type inference, we can omit the params and return types. This is true when passing closures as params to a function. 29 | reversed = array.sorted(by: {s1, s2 in return s1 > s2}) 30 | 31 | //: In case of single-expression closures, the return value is implicit, thus the return expression can be omitted. 32 | reversed = array.sorted(by: {s1, s2 in s1 == s2}) 33 | 34 | /*: In the previous examples, the names of the closure's params were explicit. 35 | You can use the $X variables to refer to params for the closure 36 | This eliminates the need for the first params list, which makes the body the only relevant part. 37 | */ 38 | reversed = array.sorted(by: {$0 == $1}) 39 | 40 | //: We can even take this to an extreme. String defines its own implementation for the ">" operator, which is really all the closure does. 41 | reversed = array.sorted(by: >) 42 | 43 | 44 | 45 | //: ## TRAILING CLOSURES 46 | func someFunctionThatTakesAClosure(closure: () -> ()) { 47 | // function body goes here 48 | } 49 | 50 | /*: 51 | Closures which are too long to be defined inline. 52 | Here's how you call this function without using a trailing closure: 53 | */ 54 | someFunctionThatTakesAClosure(closure: { 55 | // closure's body goes here 56 | }) 57 | 58 | //: Here's how you call this function with a trailing closure instead: 59 | 60 | someFunctionThatTakesAClosure() { 61 | // trailing closure's body goes here 62 | } 63 | 64 | //Sorting function with inline closure: 65 | array.sort() {$0 == $1} 66 | 67 | //: **Note**: In case the function doesn't take any params other than a trailing closure, there's no need for parenthesis. 68 | 69 | let digitNames = [ 70 | 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four", 71 | 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine" 72 | ] 73 | let numbers = [16, 58, 510] 74 | 75 | let stringsArray = numbers.map { 76 | (number) -> String in 77 | var number = number 78 | var output = "" 79 | while number > 0 { 80 | output = digitNames[number % 10]! + output //Note how the optional value returned from the dic subscript is force-unwrapped, since a value is guaranteed. 81 | number /= 10 82 | } 83 | return output 84 | } 85 | 86 | //: ## AUTOCLOSURES 87 | 88 | /*: 89 | An autoclosure is a closure that is automatically created to wrap an expression that’s being passed as an argument to a function. 90 | It doesn’t take any arguments, and when it’s called, it returns the value of the expression that’s wrapped inside of it. 91 | This syntactic convenience lets you omit braces around a function’s parameter by writing a normal expression instead of an explicit closure. 92 | 93 | An autoclosure lets you delay evaluation, because the code inside isn’t run until you call the closure. 94 | */ 95 | 96 | var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] 97 | let customerProvider = { customersInLine.remove(at: 0) } 98 | 99 | //: Traditional way 100 | func serve(customer customerProvider: () -> String) { 101 | print("Now serving \(customerProvider())!") //The closure is called here! 102 | } 103 | serve(customer: { customersInLine.remove(at: 0) } ) 104 | 105 | //: **@autoclosure** way 106 | func serve(customer customerProvider: @autoclosure () -> String) { 107 | print("Now serving \(customerProvider())!") 108 | } 109 | serve(customer: customersInLine.remove(at: 0)) //We are not required to use the curly braces, since the code will be wrapped in a closure thanks to @autoclosure 110 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/08 Enumerations.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | Definition of an Enum 17 | In this case, there's no default value for the enum members. 18 | */ 19 | enum CompassPoint { 20 | case North 21 | case South 22 | case East 23 | case West 24 | } 25 | 26 | /* 27 | Defines an enum with members with explicit types. 28 | */ 29 | enum Barcode { 30 | case UPCA(Int, Int, Int, Int) 31 | case QRCode(String) 32 | } 33 | 34 | /* 35 | In this case, the enum is defined with raw values. 36 | They must be unique 37 | */ 38 | enum ASCIIControlCharacter: Character { 39 | case Tab = "\t" 40 | case LineFeed = "\n" 41 | case CarriageReturn = "\r" 42 | } 43 | 44 | var someEnum = CompassPoint.East 45 | 46 | //Once the type is known, it can be omitted for reassignment. 47 | someEnum = .West 48 | 49 | print("This is the enum: \(someEnum)") 50 | (someEnum == .West) ? print("Equal") : print("Not Equal") 51 | 52 | var newEnum = Barcode.QRCode("162534") 53 | newEnum = Barcode.QRCode("692438") 54 | 55 | let asciiCode = ASCIIControlCharacter.Tab 56 | print("Code is \(asciiCode.rawValue)") 57 | 58 | //In this case, since it's not guaranteed to find an enum for the specified rawValue, the initializer returns an optional 59 | 60 | if let lineFeed = ASCIIControlCharacter(rawValue: "\r") { 61 | //Do something 62 | print(lineFeed) 63 | } 64 | 65 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/09 Classes & Structs.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | Classes and structures in Swift have many things in common. Both can: 17 | 18 | • Define properties to store values 19 | • Define methods to provide functionality 20 | • Define subscripts to provide access to their values using subscript syntax 21 | • Define initializers to set up their initial state 22 | • Be extended to expand their functionality beyond a default implementation 23 | • Conform to protocols to provide standard functionality of a certain kind 24 | 25 | Classes have additional capabilities that structures do not: 26 | 27 | • Inheritance enables one class to inherit the characteristics of another. 28 | • Type casting enables you to check and interpret the type of a class instance at runtime. 29 | • Deinitializers enable an instance of a class to free up any resources it has assigned. 30 | • Reference counting allows more than one reference to a class instance. 31 | 32 | NOTE 33 | 34 | Structures are always copied when they are passed around in your code, and do not use reference counting. 35 | The same applies to Enums 36 | 37 | 38 | 39 | 40 | Choosing Between Classes and Structures 41 | 42 | You can use both classes and structures to define custom data types to use as the building blocks of your program’s code. 43 | 44 | However, structure instances are always passed by value, and class instances are always passed by reference. This means that they are suited to different kinds of tasks. As you consider the data constructs and functionality that you need for a project, decide whether each data construct should be defined as a class or as a structure. 45 | 46 | As a general guideline, consider creating a structure when one or more of these conditions apply: 47 | 48 | • The structure’s primary purpose is to encapsulate a few relatively simple data values. 49 | • It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure. 50 | • Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced. 51 | • The structure does not need to inherit properties or behavior from another existing type. 52 | 53 | Examples of good candidates for structures include: 54 | 55 | • The size of a geometric shape, perhaps encapsulating a width property and a height property, both of type Double. 56 | • A way to refer to ranges within a series, perhaps encapsulating a start property and a length property, both of type Int. 57 | • A point in a 3D coordinate system, perhaps encapsulating x, y and z properties, each of type Double. 58 | In all other cases, define a class, and create instances of that class to be managed and passed by reference. In practice, this means that most custom data constructs should be classes, not structures. 59 | 60 | 61 | Assignment and Copy Behavior for Strings, Arrays, and Dictionaries 62 | 63 | Swift’s String, Array, and Dictionary types are implemented as structures. This means that strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method. 64 | 65 | This behavior is different from NSString, NSArray, and NSDictionary in Foundation, which are implemented as classes, not structures. NSString, NSArray, and NSDictionary instances are always assigned and passed around as a reference to an existing instance, rather than as a copy. 66 | */ 67 | 68 | struct Resolution { 69 | var width = 0 70 | var height = 0 71 | } 72 | 73 | class ViewController: UIViewController { 74 | 75 | var resolution = Resolution() 76 | var interlaced = false 77 | var frameRate = 0.0 78 | var name: String? 79 | 80 | override func viewDidLoad() { 81 | super.viewDidLoad() 82 | } 83 | 84 | override func didReceiveMemoryWarning() { 85 | super.didReceiveMemoryWarning() 86 | // Dispose of any resources that can be recreated. 87 | } 88 | } 89 | 90 | 91 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/10 Properties.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | ================================================= 17 | Stored Properties of Constant Structure Instances 18 | ================================================= 19 | 20 | If you create an instance of a structure and assign that instance to a constant, you cannot modify the instance’s properties, even if they were declared as variable properties. 21 | This behavior is due to structures being value types. When an instance of a value type is marked as a constant, so are all of its properties. 22 | The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties. 23 | */ 24 | 25 | struct FixedLengthRange { 26 | var firstValue: Int 27 | let length: Int 28 | 29 | //These are both stored and computed global variables, or "type" variables. They will apply to all instances of this struct, including their value. 30 | static var storedTypeProperty = "Some value." 31 | static var computedTypeProperty: Int { 32 | // return an Int value here 33 | get { 34 | //This is how type vars are accessed, by calling the class 35 | print(FixedLengthRange.storedTypeProperty) 36 | return self.computedTypeProperty 37 | } 38 | set { 39 | self.computedTypeProperty = newValue 40 | } 41 | } 42 | } 43 | 44 | class DataImporter { 45 | /* 46 | DataImporter is a class to import data from an external file. 47 | The class is assumed to take a non-trivial amount of time to initialize. 48 | */ 49 | var fileName = "data.txt" 50 | var cont: ViewController = ViewController() 51 | 52 | func doSomething() -> Void { 53 | 54 | } 55 | 56 | // the DataImporter class would provide data importing functionality here 57 | } 58 | 59 | 60 | class ViewController: UIViewController { 61 | 62 | //This is a "Stored Property". It simply provides a value and the ability to set it back. 63 | var prop = "Hello" 64 | 65 | //This is a "Computed Property". Its value is calculated in real-time, and provides getters and setters. 66 | var someCalculation: Int { 67 | get { 68 | return 1 + 1 69 | } 70 | set { 71 | self.someCalculation = newValue 72 | } 73 | } 74 | 75 | //This property has observers for when the the value will and did set 76 | var propWithObserver: Int = 0 { 77 | willSet { 78 | print(newValue) 79 | } 80 | 81 | didSet { 82 | print(oldValue) 83 | } 84 | //Note that if the didSet sets the value of the property, it doesn't call the setter again 85 | } 86 | 87 | //This is a "Computed Property" with just a getter (read-only). 88 | var someFixedCalculatedProperty: Double { 89 | return 3 * 3 90 | } 91 | 92 | //This is a type variable for the class ViewController (it'll apply for all instances). It's weirdly declared with the word "class" 93 | class var computedTypeProperty: Int { 94 | // return an Int value here 95 | get { 96 | 97 | return 1 + 1 98 | } 99 | set { 100 | self.computedTypeProperty = newValue 101 | } 102 | } 103 | 104 | override func viewDidLoad() { 105 | super.viewDidLoad() 106 | 107 | var rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4) 108 | // this range represents integer values 0, 1, 2, and 3 109 | 110 | rangeOfFourItems.firstValue = 6 111 | // this will report an error, even though firstValue is a variable property 112 | 113 | //Here, importer won't be instantiated until we use it for the first time. 114 | // lazy var importer = DataImporter() 115 | } 116 | 117 | override func didReceiveMemoryWarning() { 118 | super.didReceiveMemoryWarning() 119 | // Dispose of any resources that can be recreated. 120 | } 121 | } 122 | 123 | 124 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/11 Methods.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | There are instance methods and type (class) methods 17 | */ 18 | 19 | struct Point { 20 | var x = 0.0, y = 0.0 21 | static var xy = 0.0 22 | 23 | //This is a mutating method. Allows for modifying value types 24 | mutating func moveByX(deltaX: Double, y deltaY: Double) { 25 | //Here, the properties will be replaced with new values, thanks to the mutating prefix 26 | x += deltaX 27 | y += deltaY 28 | 29 | //Reassigning self is also possible because of the mutating prefix. Note that this is only possible for value types 30 | self = Point(x: x + deltaX, y: y + deltaY) 31 | } 32 | 33 | //This is a type method. 34 | static func unlockLevel(level: Double) { 35 | if xy > level { xy = level } 36 | } 37 | } 38 | 39 | class ViewController: UIViewController { 40 | 41 | var count = 0 42 | 43 | //This is an instance method 44 | func increment() { 45 | count += 1 46 | } 47 | 48 | //This is a class method. 49 | class func someTypeMethod() { 50 | print("Class Method") 51 | } 52 | 53 | 54 | override func viewDidLoad() { 55 | super.viewDidLoad() 56 | 57 | } 58 | 59 | override func didReceiveMemoryWarning() { 60 | super.didReceiveMemoryWarning() 61 | // Dispose of any resources that can be recreated. 62 | } 63 | } 64 | 65 | 66 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/12 Subscripts.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | struct Matrix { 16 | let rows: Int, columns: Int 17 | var grid: [Double] 18 | init(rows: Int, columns: Int) { 19 | self.rows = rows 20 | self.columns = columns 21 | grid = Array(repeating: 0.0, count: rows * columns) 22 | } 23 | func indexIsValidForRow(row: Int, column: Int) -> Bool { 24 | return row >= 0 && row < rows && column >= 0 && column < columns 25 | } 26 | /* 27 | This is how you define subscripts. 28 | In this case, the matrix is accessed via subscripts i.e. matrix[1,2] 29 | */ 30 | subscript(row: Int, column: Int) -> Double { 31 | //Subcripts can be read-write or read-only (no need for getters and setters in that case) 32 | get { 33 | assert(indexIsValidForRow(row: row, column: column), "Index out of range") 34 | return grid[(row * columns) + column] 35 | } 36 | //newValue is provided by default, but you can change the name of the received value. 37 | set { 38 | assert(indexIsValidForRow(row: row, column: column), "Index out of range") 39 | grid[(row * columns) + column] = newValue 40 | } 41 | } 42 | } 43 | 44 | class ViewController: UIViewController { 45 | 46 | var matrix = Matrix(rows: 2, columns: 2) 47 | 48 | override func viewDidLoad() { 49 | super.viewDidLoad() 50 | 51 | //This is setting up the first position of the matrix 52 | matrix[0, 0] = 2.5 53 | let number = matrix[0,0] 54 | print(number) 55 | 56 | //This call will fail, since it's out of bounds. 57 | matrix[3, 3] = 4.5 58 | 59 | } 60 | 61 | override func didReceiveMemoryWarning() { 62 | super.didReceiveMemoryWarning() 63 | // Dispose of any resources that can be recreated. 64 | } 65 | } 66 | 67 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/13 Inheritance.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | //Swift classes do not inherit from a universal base class. Classes you define without specifying a superclass automatically become base classes for you to build upon. 16 | 17 | /* 18 | When you provide a method, property, or subscript override for a subclass, it is sometimes useful 19 | to use the existing superclass implementation as part of your override. For example, you can refine the 20 | behavior of that existing implementation, or store a modified value in an existing inherited variable. 21 | 22 | Where this is appropriate, you access the superclass version of a method, property, or subscript by using the super prefix: 23 | 24 | • An overridden method named someMethod() can call the superclass version of someMethod() by calling super.someMethod() within the overriding method implementation. 25 | • An overridden property called someProperty can access the superclass version of someProperty as super.someProperty within the overriding getter or setter implementation. 26 | • An overridden subscript for someIndex can access the superclass version of the same subscript as super[someIndex] from within the overriding subscript implementation. 27 | */ 28 | 29 | class Vehicle { 30 | var currentSpeed = 0.0 31 | var description: String { 32 | return "traveling at \(currentSpeed) miles per hour" 33 | } 34 | func makeNoise() { 35 | // do nothing - an arbitrary vehicle doesn't necessarily make a noise 36 | } 37 | } 38 | 39 | class Bicycle: Vehicle { 40 | var hasBasket = false 41 | } 42 | 43 | class Tandem: Bicycle { 44 | var currentNumberOfPassengers = 0 45 | } 46 | 47 | class Train: Vehicle { 48 | //Here, we completely changed the base class method implementation for the one defined below. 49 | override func makeNoise() { 50 | print("Choo Choo") 51 | } 52 | } 53 | 54 | class Car: Vehicle { 55 | var gear = 1 56 | //Here, we are overriding the computed property, adding new behavior 57 | override var description: String { 58 | return super.description + " in gear \(gear)" 59 | } 60 | 61 | final func activateAirBags(){ 62 | // - This is the definitive way of activating air bags. 63 | } 64 | } 65 | 66 | class AutomaticCar: Car { 67 | //This adds a property observer to an inherited property. 68 | override var currentSpeed: Double { 69 | didSet { 70 | gear = Int(currentSpeed / 10.0) + 1 71 | } 72 | } 73 | } 74 | 75 | class ViewController: UIViewController { 76 | 77 | override func viewDidLoad() { 78 | super.viewDidLoad() 79 | 80 | let bike = Bicycle() 81 | bike.hasBasket = true 82 | bike.description 83 | 84 | let tandem = Tandem() 85 | tandem.currentNumberOfPassengers = 7 86 | } 87 | 88 | override func didReceiveMemoryWarning() { 89 | super.didReceiveMemoryWarning() 90 | // Dispose of any resources that can be recreated. 91 | } 92 | } 93 | 94 | 95 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/14 Initialization.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | 16 | struct Celsius { 17 | var temperatureInCelsius: Double 18 | init(fromFahrenheit fahrenheit: Double) { 19 | temperatureInCelsius = (fahrenheit - 32.0) / 1.8 20 | } 21 | init(fromKelvin kelvin: Double) { 22 | temperatureInCelsius = kelvin - 273.15 23 | } 24 | init(_ celsius: Double) { 25 | temperatureInCelsius = celsius 26 | } 27 | } 28 | 29 | /* 30 | For the struct, a memberwise initializer is provided. This means that stored properties don't 31 | necessarily need to have an initial value. A default initializer is created for all of them. 32 | */ 33 | struct Other { 34 | var temp: Double 35 | var otherProp: Int = 10 36 | } 37 | 38 | struct Size { 39 | var width = 0.0, height = 0.0 40 | } 41 | struct Point { 42 | var x = 0.0, y = 0.0 43 | } 44 | 45 | /* 46 | In this case, the second initializer performs delegation, which is 47 | calling another initializer within the struct. This is only valid for 48 | value types, and not classes! 49 | */ 50 | struct Rect { 51 | var origin = Point() 52 | var size = Size() 53 | init() {} 54 | init(origin: Point, size: Size) { 55 | self.origin = origin 56 | self.size = size 57 | } 58 | init(center: Point, size: Size) { 59 | let originX = center.x - (size.width / 2) 60 | let originY = center.y - (size.height / 2) 61 | self.init(origin: Point(x: originX, y: originY), size: size) 62 | } 63 | } 64 | 65 | /* 66 | ================================== 67 | */ 68 | 69 | /* 70 | For a class, every stored property must have an initial value, or have a value assigned to it inside the initializer. 71 | This reference image explains the relationship between designated initializers and convenience initializers. 72 | https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/initializerDelegation01_2x.png 73 | • Rule 1 74 | A designated initializer must call a designated initializer from its immediate superclass. 75 | 76 | • Rule 2 77 | A convenience initializer must call another initializer from the same class. 78 | 79 | • Rule 3 80 | A convenience initializer must ultimately call a designated initializer. 81 | 82 | A simple way to remember this is: 83 | 84 | - Designated initializers must always delegate up. 85 | - Convenience initializers must always delegate across. 86 | 87 | 88 | • Phase 1 89 | 90 | - A designated or convenience initializer is called on a class. 91 | - Memory for a new instance of that class is allocated. The memory is not yet initialized. 92 | - A designated initializer for that class confirms that all stored properties introduced by that class have a value. The memory for these stored properties is now initialized. 93 | - The designated initializer hands off to a superclass initializer to perform the same task for its own stored properties. 94 | - This continues up the class inheritance chain until the top of the chain is reached. 95 | - Once the top of the chain is reached, and the final class in the chain has ensured that all of its store 96 | properties have a value, the instance’s memory is considered to be fully initialized, and phase 1 is complete. 97 | 98 | • Phase 2 99 | 100 | - Working back down from the top of the chain, each designated initializer in the chain has the option to 101 | customize the instance further. Initializers are now able to access self and can modify its properties, call its instance methods, and so on. 102 | - Finally, any convenience initializers in the chain have the option to customize the instance and to work with self. 103 | 104 | Also, keep in mind that: 105 | • Rule 1 106 | If your subclass doesn’t define any designated initializers, it automatically inherits all of its superclass designated initializers. 107 | 108 | • Rule 2 109 | If your subclass provides an implementation of all of its superclass designated initializers—either by inheriting them as 110 | per rule 1, or by providing a custom implementation as part of its definition—then it automatically inherits all of the superclass convenience initializers. 111 | 112 | NOTE 113 | A subclass can implement a superclass designated initializer as a subclass convenience initializer as part of satisfying rule 2. 114 | 115 | 116 | */ 117 | 118 | class Human { 119 | var gender: String 120 | init(){ 121 | self.gender = "Female" 122 | } 123 | } 124 | 125 | class Person: Human { 126 | var name: String 127 | init(fullName name: String){ 128 | //Phase 1: Initialize class-defined properties and call the superclass initializer. 129 | self.name = name 130 | super.init() 131 | //------- 132 | 133 | //Phase 2: Further customization of local and inherited properties. 134 | self.gender = "Male" 135 | //------- 136 | } 137 | convenience init(partialName name: String){ 138 | //Phase 1: Call designated initializer 139 | let newName = "\(name) Karmy" 140 | self.init(fullName: newName) 141 | //------- 142 | 143 | //Phase 2: Access to self and properties 144 | self.name = "John Karmy" 145 | //------- 146 | 147 | } 148 | } 149 | 150 | /* 151 | ================================== 152 | */ 153 | 154 | /* 155 | Failable initializers allow us to return nil during initialization in case there was a problem. 156 | The object being initalized is treated as an optional. 157 | You can also define a failable initializer that returns an implicitly unwrapped optional instance by writing init! 158 | */ 159 | 160 | // For enums, nil can be returned at any point of initalizations 161 | 162 | enum TemperatureUnit { 163 | case Kelvin, Celsius, Fahrenheit 164 | init?(symbol: Character) { 165 | switch symbol { 166 | case "K": 167 | self = .Kelvin 168 | case "C": 169 | self = .Celsius 170 | case "F": 171 | self = .Fahrenheit 172 | default: 173 | return nil 174 | } 175 | } 176 | } 177 | 178 | // For class instances, nil can only be returned after initalizing all properties. 179 | 180 | class Product { 181 | let name: String! 182 | init?(name: String) { 183 | self.name = name 184 | if name.isEmpty { return nil } 185 | } 186 | } 187 | 188 | /* 189 | ================================== 190 | */ 191 | 192 | /* 193 | You can pre-initialize properties by running code inside a closure. Since the execution happens before all other properties are initialized, 194 | you can't access other properties nor call self inside the closure. 195 | */ 196 | 197 | struct Checkerboard { 198 | let boardColors: [Bool] = { 199 | var temporaryBoard = [Bool]() 200 | var isBlack = false 201 | for i in 1...10 { 202 | for j in 1...10 { 203 | temporaryBoard.append(isBlack) 204 | isBlack = !isBlack 205 | } 206 | isBlack = !isBlack 207 | } 208 | return temporaryBoard 209 | }() //Note that these parenthesis indicate that you want to run the closure immediately. 210 | func squareIsBlackAtRow(row: Int, column: Int) -> Bool { 211 | return boardColors[(row * 10) + column] 212 | } 213 | } 214 | 215 | /* 216 | ================================== 217 | */ 218 | 219 | class ViewController: UIViewController { 220 | 221 | override func viewDidLoad() { 222 | let bodyTemperature = Celsius(37.0) 223 | print((bodyTemperature.temperatureInCelsius)) 224 | 225 | let person = Person(fullName: "John") 226 | print(person.name) 227 | 228 | let other = Other(temp: 20, otherProp: 10) 229 | print(other.otherProp) 230 | 231 | if let product = Product(name: "Apple"){ 232 | print("Product is not nil. Names \(product.name)") 233 | } 234 | 235 | } 236 | } 237 | 238 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/15 Deinitialization.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | // Deinitializers are only available on class types. 16 | /* 17 | Deinitializers are called automatically, just before instance deallocation takes place. 18 | You are not allowed to call a deinitializer yourself. 19 | Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer 20 | is called automatically at the end of a subclass deinitializer implementation. 21 | Superclass deinitializers are always called, even if a subclass does not provide its own deinitializer. 22 | */ 23 | 24 | class Bank { 25 | static var coinsInBank = 10_000 26 | static func vendCoins(numberOfCoinsToVend: Int) -> Int { 27 | let numberOfCoinsAllowedToVend = min(numberOfCoinsToVend, coinsInBank) 28 | coinsInBank -= numberOfCoinsAllowedToVend 29 | return numberOfCoinsAllowedToVend 30 | } 31 | static func receiveCoins(coins: Int) { 32 | coinsInBank += coins 33 | } 34 | } 35 | 36 | class Player { 37 | var coinsInPurse: Int 38 | init(coins: Int) { 39 | coinsInPurse = Bank.vendCoins(numberOfCoinsToVend: coins) 40 | } 41 | func winCoins(coins: Int) { 42 | coinsInPurse += Bank.vendCoins(numberOfCoinsToVend: coins) 43 | } 44 | deinit { 45 | Bank.receiveCoins(coins: coinsInPurse) 46 | } 47 | } 48 | 49 | /* 50 | An optional variable is used here, because players can leave the game at any point. 51 | The optional lets you track whether there is currently a player in the game. 52 | */ 53 | var playerOne: Player? = Player(coins: 100) 54 | print("A new player has joined the game with \(playerOne!.coinsInPurse) coins") 55 | // prints "A new player has joined the game with 100 coins" 56 | print("There are now \(Bank.coinsInBank) coins left in the bank") 57 | // prints "There are now 9900 coins left in the bank" 58 | 59 | 60 | playerOne!.winCoins(coins: 2_000) 61 | print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins") 62 | // prints "PlayerOne won 2000 coins & now has 2100 coins" 63 | print("The bank now only has \(Bank.coinsInBank) coins left") 64 | // prints "The bank now only has 7900 coins left" 65 | 66 | 67 | playerOne = nil //Just before this happens, its deinitializer is called automatically. 68 | print("PlayerOne has left the game") 69 | // prints "PlayerOne has left the game" 70 | print("The bank now has \(Bank.coinsInBank) coins") 71 | // prints "The bank now has 10000 coins" 72 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/16 ARC.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | Reference counting only applies to instances of classes. Structures and enumerations are value types, 17 | not reference types, and are not stored and passed by reference. 18 | */ 19 | 20 | class Person { 21 | let name: String 22 | init(name: String) { 23 | self.name = name 24 | print("\(name) is being initialized") 25 | } 26 | deinit { 27 | print("\(name) is being deinitialized") 28 | } 29 | } 30 | 31 | // At this point, these references are nil. 32 | var reference1: Person? 33 | var reference2: Person? 34 | var reference3: Person? 35 | 36 | reference1 = Person(name: "John Appleseed") 37 | 38 | //At this point 3 strong references of "John Appleseed" are being stored. 39 | reference2 = reference1 40 | reference3 = reference1 41 | 42 | //John is still alive 43 | reference1 = nil 44 | reference2 = nil 45 | 46 | //John is dead by now. 47 | reference3 = nil 48 | 49 | 50 | /* 51 | =============================================== 52 | Strong Reference Cycles Between Class Instances 53 | =============================================== 54 | */ 55 | 56 | class Apartment { 57 | let unit: String 58 | init(unit: String) { self.unit = unit } 59 | var tenant: Person? 60 | deinit { print("Apartment \(unit) is being deinitialized") } 61 | } 62 | 63 | class Tenant : Person { 64 | var apartment: Apartment? 65 | } 66 | 67 | var john: Tenant? 68 | var unit4A: Apartment? 69 | 70 | john = Tenant(name: "John Appleseed") 71 | unit4A = Apartment(unit: "4A") 72 | 73 | //Here's where the reference cycle is created. 74 | john!.apartment = unit4A 75 | unit4A!.tenant = john 76 | 77 | // The variables are still references from inside the properties. This creates the reference cycle, 78 | // and therefore, a memory leak. 79 | // A simple way around this would be to manually set the apartment and tenant properties to nil, and then set the outside references to nil. 80 | john = nil 81 | unit4A = nil 82 | 83 | 84 | /* 85 | ========================================================= 86 | Resolving Strong Reference Cycles Between Class Instances 87 | ========================================================= 88 | 89 | Weak and unowned references enable one instance in a reference cycle to refer to the other instance 90 | without keeping a strong hold on it. The instances can then refer to each other without creating a strong reference cycle. 91 | 92 | Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. 93 | Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization. 94 | */ 95 | 96 | // Weak References 97 | /* 98 | Use a weak reference to avoid reference cycles whenever it is possible for that reference to have “no value” 99 | at some point in its life. If the reference will always have a value, use an unowned reference instead, 100 | as described in Unowned References. In the Apartment example above, it is appropriate for an apartment to be able to 101 | have “no tenant” at some point in its lifetime, and so a weak reference is an appropriate way to break the reference cycle in this case. 102 | 103 | NOTE 104 | 105 | Weak references must be declared as variables, to indicate that their value can change at runtime. A weak reference cannot be declared as a constant. 106 | */ 107 | 108 | 109 | //Unowned References 110 | 111 | /* 112 | Like weak references, an unowned reference does not keep a strong hold on the instance it refers to. Unlike a weak reference, 113 | however, an unowned reference is assumed to always have a value. Because of this, an unowned reference is always defined as a 114 | nonoptional type. You indicate an unowned reference by placing the unowned keyword before a property or variable declaration. 115 | 116 | Because an unowned reference is nonoptional, you don’t need to unwrap the unowned reference each time it is used. 117 | An unowned reference can always be accessed directly. However, ARC cannot set the reference to nil when the instance it refers 118 | to is deallocated, because variables of a nonoptional type cannot be set to nil. 119 | 120 | NOTE 121 | 122 | If you try to access an unowned reference after the instance that it references is deallocated, you will trigger a runtime error. 123 | Use unowned references only when you are sure that the reference will always refer to an instance. 124 | 125 | Note also that Swift guarantees your app will crash if you try to access an unowned reference after the instance it references is deallocated. 126 | You will never encounter unexpected behavior in this situation. Your app will always crash reliably, although you should, of course, prevent it from doing so. 127 | 128 | */ 129 | 130 | class Customer { 131 | let name: String 132 | var card: CreditCard? 133 | init(name: String) { 134 | self.name = name 135 | } 136 | deinit { print("\(name) is being deinitialized") } 137 | } 138 | 139 | class CreditCard { 140 | let number: UInt64 141 | unowned let customer: Customer 142 | init(number: UInt64, customer: Customer) { 143 | self.number = number 144 | self.customer = customer 145 | } 146 | deinit { print("Card #\(number) is being deinitialized") } 147 | } 148 | 149 | var mike: Customer? 150 | mike = Customer(name: "Mike Appleseed") 151 | mike!.card = CreditCard(number: 1234_5678_9012_3456, customer: mike!) 152 | mike = nil 153 | 154 | 155 | /* 156 | =============================================================== 157 | Unowned References and Implicitly Unwrapped Optional Properties 158 | =============================================================== 159 | 160 | However, there is a third scenario, in which both properties should always have a value, and neither property should ever be 161 | nil once initialization is complete. In this scenario, it is useful to combine an unowned property on one class with an implicitly 162 | unwrapped optional property on the other class. 163 | 164 | This enables both properties to be accessed directly (without optional unwrapping) once initialization is complete, while still 165 | avoiding a reference cycle. This section shows you how to set up such a relationship. 166 | */ 167 | 168 | 169 | class Country { 170 | let name: String 171 | var capitalCity: City! 172 | init(name: String, capitalName: String) { 173 | self.name = name 174 | self.capitalCity = City(name: capitalName, country: self) 175 | } 176 | } 177 | 178 | class City { 179 | let name: String 180 | unowned let country: Country 181 | init(name: String, country: Country) { 182 | self.name = name 183 | self.country = country 184 | } 185 | } 186 | 187 | /* 188 | The initializer for City is called from within the initializer for Country. However, the initializer for Country cannot pass 189 | self to the City initializer until a new Country instance is fully initialized, as described in Two-Phase Initialization. 190 | 191 | To cope with this requirement, you declare the capitalCity property of Country as an implicitly unwrapped optional property, 192 | indicated by the exclamation mark at the end of its type annotation (City!). This means that the capitalCity property has a 193 | default value of nil, like any other optional, but can be accessed without the need to unwrap its value as described in Implicitly Unwrapped Optionals. 194 | 195 | Because capitalCity has a default nil value, a new Country instance is considered fully initialized as soon as the Country instance 196 | sets its name property within its initializer. This means that the Country initializer can start to reference and pass around the 197 | implicit self property as soon as the name property is set. The Country initializer can therefore pass self as one of the parameters 198 | for the City initializer when the Country initializer is setting its own capitalCity property. 199 | */ 200 | 201 | 202 | 203 | /* 204 | ==================================== 205 | Strong Reference Cycles for Closures 206 | ==================================== 207 | 208 | A strong reference cycle can also occur if you assign a closure to a property of a class instance, and the body of that 209 | closure captures the instance. This capture might occur because the closure’s body accesses a property of the instance, 210 | such as self.someProperty, or because the closure calls a method on the instance, such as self.someMethod(). In either case, 211 | these accesses cause the closure to “capture” self, creating a strong reference cycle. 212 | 213 | Swift provides an elegant solution to this problem, known as a closure capture list. 214 | */ 215 | 216 | class HTMLElement { 217 | 218 | let name: String 219 | let text: String? 220 | 221 | lazy var asHTML: (Void) -> String = { 222 | if let text = self.text { 223 | return "<\(self.name)>\(text)" 224 | } else { 225 | return "<\(self.name) />" 226 | } 227 | } 228 | 229 | init(name: String, text: String? = nil) { 230 | self.name = name 231 | self.text = text 232 | } 233 | 234 | deinit { 235 | print("\(name) is being deinitialized") 236 | } 237 | 238 | } 239 | 240 | /* 241 | A capture list defines the rules to use when capturing one or more reference types within the closure’s body. 242 | As with strong reference cycles between two class instances, you declare each captured reference to be a weak or unowned reference rather than a strong reference. 243 | */ 244 | 245 | class HTMLElement2 { 246 | 247 | let name: String 248 | let text: String? 249 | 250 | lazy var asHTML: (Void) -> String = { 251 | [unowned self] in //Closure List 252 | if let text = self.text { 253 | return "<\(self.name)>\(text)" 254 | } else { 255 | return "<\(self.name) />" 256 | } 257 | } 258 | 259 | init(name: String, text: String? = nil) { 260 | self.name = name 261 | self.text = text 262 | } 263 | 264 | deinit { 265 | print("\(name) is being deinitialized") 266 | } 267 | 268 | } 269 | 270 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/17 Optional Chaining.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | ======================================================== 17 | Optional Chaining as an Alternative to Forced Unwrapping 18 | ======================================================== 19 | */ 20 | 21 | /* 22 | The main difference is that optional chaining fails gracefully when the optional is nil, 23 | whereas forced unwrapping triggers a runtime error when the optional is nil. 24 | 25 | The result of an optional chaining call is always an optional value, even if the property, 26 | method, or subscript you are querying returns a nonoptional value. 27 | 28 | Specifically, the result of an optional chaining call is of the same type as 29 | the expected return value, but wrapped in an optional. 30 | */ 31 | 32 | class Person { 33 | var residence: Residence? 34 | } 35 | 36 | class Residence { 37 | var numberOfRooms = 1 38 | } 39 | 40 | let john = Person() 41 | //This creates a run-time error: Unwrapping the "residence" property, which is an optional, and its value is nil 42 | //let roomCount = john.residence!.numberOfRooms 43 | 44 | //Doing it with optional chaining 45 | 46 | if let roomCount = john.residence?.numberOfRooms { 47 | print("John's residence has \(roomCount) room(s).") 48 | } else { 49 | print("Unable to retrieve the number of rooms.") 50 | } 51 | 52 | john.residence = Residence() 53 | 54 | if let roomCount = john.residence?.numberOfRooms { 55 | print("John's residence has \(roomCount) room(s).") 56 | } else { 57 | print("Unable to retrieve the number of rooms.") 58 | } 59 | 60 | /* 61 | ============================================ 62 | Defining Model Classes for Optional Chaining 63 | ============================================ 64 | */ 65 | 66 | class OtherPerson { 67 | var residence: OtherResidence? 68 | } 69 | 70 | class OtherResidence { 71 | var rooms = [Room]() 72 | var numberOfRooms: Int { 73 | return rooms.count 74 | } 75 | subscript(i: Int) -> Room { 76 | get { 77 | return rooms[i] 78 | } 79 | set { 80 | rooms[i] = newValue 81 | } 82 | } 83 | func printNumberOfRooms() { 84 | print("The number of rooms is \(numberOfRooms)") 85 | } 86 | var address: Address? 87 | } 88 | 89 | class Room { 90 | let name: String 91 | init(name: String) { self.name = name } 92 | } 93 | 94 | class Address { 95 | var buildingName: String? 96 | var buildingNumber: String? 97 | var street: String? 98 | func buildingIdentifier() -> String? { 99 | if buildingName != nil { 100 | return buildingName 101 | } else if buildingNumber != nil && street != nil { 102 | return "\(buildingNumber) \(street)" 103 | } else { 104 | return nil 105 | } 106 | } 107 | } 108 | 109 | var otherResidence = OtherResidence() 110 | otherResidence.rooms.append(Room(name: "Living Room")) 111 | var room = otherResidence[0] 112 | 113 | 114 | /* 115 | ============================================== 116 | Accessing Properties Through Optional Chaining 117 | ============================================== 118 | */ 119 | 120 | let bob = OtherPerson() 121 | 122 | if let roomCount = bob.residence?.numberOfRooms { 123 | print("John's residence has \(roomCount) room(s).") 124 | } else { 125 | print("Unable to retrieve the number of rooms.") 126 | } 127 | 128 | /* 129 | In this example, the attempt to set the address property of john.residence will fail, 130 | because john.residence is currently nil. 131 | 132 | The assignment is part of the optional chaining, which means none of the code on the 133 | right hand side of the = operator is evaluated. 134 | */ 135 | 136 | let someAddress = Address() 137 | someAddress.buildingNumber = "29" 138 | someAddress.street = "Acacia Road" 139 | bob.residence?.address = someAddress 140 | 141 | func createAddress() -> Address { 142 | print("Function was called.") 143 | 144 | let someAddress = Address() 145 | someAddress.buildingNumber = "29" 146 | someAddress.street = "Acacia Road" 147 | 148 | return someAddress 149 | } 150 | 151 | bob.residence?.address = createAddress() 152 | bob.residence = otherResidence 153 | 154 | /* 155 | If you call this method on an optional value with optional chaining, the method’s return type will be Void?, 156 | not Void, because return values are always of an optional type when called through optional chaining. 157 | This enables you to use an if statement to check whether it was possible to call the 158 | printNumberOfRooms() method, even though the method does not itself define a return value. 159 | */ 160 | 161 | if let void = bob.residence?.printNumberOfRooms() { 162 | print("It was possible to print the number of rooms.") 163 | } else { 164 | print("It was not possible to print the number of rooms.") 165 | } 166 | 167 | /* 168 | Any attempt to set a property through optional chaining returns a value of type Void?, 169 | which enables you to compare against nil to see if the property was set successfully: 170 | */ 171 | 172 | if (bob.residence?.address = someAddress) != nil { 173 | print("It was possible to set the address.") 174 | } else { 175 | print("It was not possible to set the address.") 176 | } 177 | 178 | /* 179 | ============================================== 180 | Accessing Subscripts Through Optional Chaining 181 | ============================================== 182 | */ 183 | 184 | if let firstRoomName = bob.residence?[0].name { 185 | print("The first room name is \(firstRoomName).") 186 | } else { 187 | print("Unable to retrieve the first room name.") 188 | } 189 | 190 | bob.residence?.rooms.append(Room(name: "Bathroom")) 191 | 192 | 193 | /* 194 | Accessing Subscripts of Optional Type 195 | */ 196 | 197 | var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]] 198 | testScores["Dave"]?[0] = 91 199 | testScores["Bev"]?[0] += 1 200 | testScores["Brian"]?[0] = 72 201 | 202 | // the "Dave" array is now [91, 82, 84] and the "Bev" array is now [80, 94, 81] 203 | testScores["Dave"] 204 | testScores["Bev"] 205 | 206 | /* 207 | - If you try to retrieve an Int value through optional chaining, an Int? is always returned, 208 | no matter how many levels of chaining are used. 209 | 210 | - Similarly, if you try to retrieve an Int? value through optional chaining, 211 | an Int? is always returned, no matter how many levels of chaining are used. 212 | */ 213 | 214 | if let bobsStreet = bob.residence?.address?.street { 215 | print("Bob's street name is \(bobsStreet).") 216 | } else { 217 | print("Unable to retrieve the address.") 218 | } 219 | 220 | /* 221 | Chaining on Methods with Optional Return Values 222 | */ 223 | 224 | if let beginsWithThe = 225 | bob.residence?.address?.buildingIdentifier()?.hasPrefix("The") { 226 | if beginsWithThe { 227 | print("John's building identifier begins with \"The\".") 228 | } else { 229 | print("John's building identifier does not begin with \"The\".") 230 | } 231 | } 232 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/18 Error Handling.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | ================================ 17 | Representing and Throwing Errors 18 | ================================ 19 | */ 20 | 21 | /* 22 | Swift enumerations are particularly well suited to modeling a group of related error conditions, 23 | with associated values allowing for additional information about the nature of an error to be communicated. 24 | */ 25 | 26 | enum VendingMachineError: ErrorProtocol { 27 | case InvalidSelection 28 | case InsufficientFunds(coinsNeeded: Int) 29 | case OutOfStock 30 | } 31 | 32 | throw VendingMachineError.InsufficientFunds(coinsNeeded: 5) 33 | 34 | /* 35 | Error handling in Swift resembles exception handling in other languages, with the use of the try, catch and throw keywords. 36 | Unlike exception handling in many languages—including Objective-C—error handling in Swift does not involve unwinding the call stack, 37 | a process that can be computationally expensive. As such, the performance characteristics of a throw statement are comparable to those of a return statement. 38 | */ 39 | 40 | /* 41 | =========================================== 42 | Propagating Errors Using Throwing Functions 43 | =========================================== 44 | */ 45 | 46 | /* 47 | To indicate that a function, method, or initializer can throw an error, 48 | you write the throws keyword in the function’s declaration after its parameters. 49 | */ 50 | 51 | func canThrowErrors() throws -> String { return "" } 52 | 53 | func cannotThrowErrors() -> String { return "" } 54 | // A throwing function propagates errors that are thrown inside of it to the scope from which it’s called. 55 | // Only throwing functions can propagate errors. Any errors thrown inside a nonthrowing function must be handled inside the function. 56 | 57 | struct Item { 58 | var price: Int 59 | var count: Int 60 | } 61 | 62 | class VendingMachine { 63 | var inventory = [ 64 | "Candy Bar": Item(price: 12, count: 7), 65 | "Chips": Item(price: 10, count: 4), 66 | "Pretzels": Item(price: 7, count: 11) 67 | ] 68 | var coinsDeposited = 0 69 | func dispenseSnack(snack: String) { 70 | print("Dispensing \(snack)") 71 | } 72 | 73 | func vend(itemNamed name: String) throws { 74 | guard var item = inventory[name] else { 75 | throw VendingMachineError.InvalidSelection 76 | } 77 | 78 | guard item.count > 0 else { 79 | throw VendingMachineError.OutOfStock 80 | } 81 | 82 | guard item.price <= coinsDeposited else { 83 | throw VendingMachineError.InsufficientFunds(coinsNeeded: item.price - coinsDeposited) 84 | } 85 | 86 | coinsDeposited -= item.price 87 | item.count -= 1 88 | inventory[name] = item 89 | dispenseSnack(snack: name) 90 | } 91 | } 92 | 93 | /* 94 | The implementation of the vend(itemNamed:) method uses guard statements to exit the method early 95 | and throw appropriate errors if any of the requirements for purchasing a snack aren’t met. 96 | Because a throw statement immediately transfers program control, an item will be vended only if all of these requirements are met. 97 | */ 98 | 99 | 100 | /* 101 | ============================== 102 | Handling Errors Using Do-Catch 103 | ============================== 104 | */ 105 | 106 | func buyFavoriteSnack(name: String, vendingMachine: VendingMachine) throws{ 107 | throw VendingMachineError.InvalidSelection 108 | } 109 | 110 | 111 | var vendingMachine = VendingMachine() 112 | vendingMachine.coinsDeposited = 8 113 | do { 114 | try buyFavoriteSnack(name: "Alice", vendingMachine: vendingMachine) 115 | } catch VendingMachineError.InvalidSelection { 116 | print("Invalid Selection.") 117 | } catch VendingMachineError.OutOfStock { 118 | print("Out of Stock.") 119 | } catch VendingMachineError.InsufficientFunds(let coinsNeeded) { 120 | print("Insufficient funds. Please insert an additional \(coinsNeeded) coins.") 121 | } 122 | 123 | 124 | /* 125 | ==================================== 126 | Converting Errors to Optional Values 127 | ==================================== 128 | */ 129 | 130 | func someThrowingFunction() throws -> Int { 131 | // ... 132 | return 2 133 | } 134 | 135 | let x = try? someThrowingFunction() 136 | 137 | let y: Int? 138 | do { 139 | y = try someThrowingFunction() 140 | } catch { 141 | y = nil 142 | } 143 | 144 | 145 | /* 146 | If someThrowingFunction() throws an error, the value of x and y is nil. Otherwise, the value of x and y 147 | is the value that the function returned. Note that x and y are an optional of whatever type someThrowingFunction() returns. 148 | Here the function returns an integer, so x and y are optional integers. 149 | 150 | Using try? lets you write concise error handling code when you want to handle all errors in the same way. 151 | For example, the following code uses several approaches to fetch data, or returns nil if all of the approaches fail. 152 | */ 153 | 154 | 155 | 156 | /* 157 | =========================== 158 | Disabling Error Propagation 159 | =========================== 160 | */ 161 | 162 | func loadImage(path: String) throws ->String { 163 | return "Image" 164 | } 165 | 166 | let photo = try! loadImage(path: "./Resources/John Appleseed.jpg") 167 | 168 | 169 | /* 170 | Sometimes you know a throwing function or method won’t, in fact, throw an error at runtime. 171 | On those occasions, you can write try! before the expression to disable error propagation and wrap the call in a 172 | runtime assertion that no error will be thrown. If an error actually is thrown, you’ll get a runtime error. 173 | */ 174 | 175 | 176 | /* 177 | ========================== 178 | Specifying Cleanup Actions 179 | ========================== 180 | */ 181 | 182 | func exists(file: String) -> Bool{ 183 | return true 184 | } 185 | 186 | func openFile(file: String) -> String{ 187 | return "" 188 | } 189 | 190 | func close(file: String) -> Void{ 191 | 192 | } 193 | 194 | func processFile(filename: String) throws { 195 | if exists(file: filename) { 196 | let file = openFile(file: filename) 197 | defer { 198 | close(file: file) 199 | } 200 | // while let line = try file.readline() { 201 | // // Work with the file. 202 | // } 203 | // close(file) is called here, at the end of the scope. 204 | } 205 | } 206 | 207 | 208 | /* 209 | You use a defer statement to execute a set of statements just before code execution leaves the current block of code. 210 | This statement lets you do any necessary cleanup that should be performed regardless of how execution leaves the current block 211 | of code—whether it leaves because an error was thrown or because of a statement such as return or break. 212 | For example, you can use a defer statement to ensure that file descriptors are closed and manually allocated memory is freed. 213 | 214 | A defer statement defers execution until the current scope is exited. This statement consists of the defer keyword and the statements 215 | to be executed later. The deferred statements may not contain any code that would transfer control out of the statements, 216 | such as a break or a return statement, or by throwing an error. Deferred actions are executed in reverse order of how they are 217 | specified—that is, the code in the first defer statement executes after code in the second, and so on. 218 | 219 | You can use a defer statement even when no error handling code is involved. 220 | */ 221 | 222 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/19 Type Casting.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | // |=------------------------------------------------------=| 2 | // Copyright (c) 2016 Juan Antonio Karmy. 3 | // Licensed under MIT License 4 | // 5 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 6 | // 7 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 8 | // 9 | // |=------------------------------------------------------=| 10 | 11 | 12 | import UIKit 13 | 14 | /* 15 | =========================================== 16 | Defining a Class Hierarchy for Type Casting 17 | =========================================== 18 | */ 19 | 20 | class MediaItem { 21 | var name: String 22 | init(name: String) { 23 | self.name = name 24 | } 25 | } 26 | 27 | class Movie: MediaItem { 28 | var director: String 29 | init(name: String, director: String) { 30 | self.director = director 31 | super.init(name: name) 32 | } 33 | } 34 | 35 | class Song: MediaItem { 36 | var artist: String 37 | init(name: String, artist: String) { 38 | self.artist = artist 39 | super.init(name: name) 40 | } 41 | } 42 | 43 | let library = [ 44 | Movie(name: "Casablanca", director: "Michael Curtiz"), 45 | Song(name: "Blue Suede Shoes", artist: "Elvis Presley"), 46 | Movie(name: "Citizen Kane", director: "Orson Welles"), 47 | Song(name: "The One And Only", artist: "Chesney Hawkes"), 48 | Song(name: "Never Gonna Give You Up", artist: "Rick Astley") 49 | ] 50 | 51 | /* 52 | The type of the library array is inferred by initializing it with the contents of an array literal. 53 | Swift’s type checker is able to deduce that Movie and Song have a common superclass of MediaItem, 54 | and so it infers a type of [MediaItem] for the library array. 55 | 56 | The items stored in library are still Movie and Song instances behind the scenes. 57 | However, if you iterate over the contents of this array, the items you receive back are typed as MediaItem, 58 | and not as Movie or Song. In order to work with them as their native type, you need to check their type, 59 | or downcast them to a different type, as described below. 60 | */ 61 | 62 | 63 | /* 64 | ============= 65 | Checking Type 66 | ============= 67 | */ 68 | 69 | /* 70 | Use the type check operator (is) to check whether an instance is of a certain subclass type. 71 | */ 72 | 73 | var movieCount = 0 74 | var songCount = 0 75 | 76 | for item in library { 77 | if item is Movie { 78 | movieCount += 1 79 | } else if item is Song { 80 | songCount += 1 81 | } 82 | } 83 | 84 | print("Media library contains \(movieCount) movies and \(songCount) songs") 85 | // Prints "Media library contains 2 movies and 3 songs" 86 | 87 | 88 | /* 89 | =========== 90 | Downcasting 91 | =========== 92 | */ 93 | 94 | /* 95 | A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. 96 | Where you believe this is the case, you can try to downcast to the subclass type with a type cast operator (as? or as!). 97 | 98 | Because downcasting can fail, the type cast operator comes in two different forms. The conditional form, as?, returns 99 | an optional value of the type you are trying to downcast to. The forced form, as!, attempts the downcast and force-unwraps 100 | the result as a single compound action. 101 | */ 102 | 103 | 104 | for item in library { 105 | if let movie = item as? Movie { 106 | print("Movie: '\(movie.name)', dir. \(movie.director)") 107 | } else if let song = item as? Song { 108 | print("Song: '\(song.name)', by \(song.artist)") 109 | } 110 | } 111 | 112 | // Note that "let mediaItem = movie as MediaItem" will always work. That's why you don't need to use neither the conditional form 113 | // or the forced form. 114 | 115 | 116 | /* 117 | ================================== 118 | Type Casting for Any and AnyObject 119 | ================================== 120 | */ 121 | 122 | /* 123 | Swift provides two special type aliases for working with non-specific types: 124 | 125 | AnyObject can represent an instance of any class type. 126 | Any can represent an instance of any type at all, including function types. 127 | */ 128 | 129 | 130 | /* 131 | ========= 132 | AnyObject 133 | ========= 134 | */ 135 | 136 | 137 | let someObjects: [AnyObject] = [ 138 | Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"), 139 | Movie(name: "Moon", director: "Duncan Jones"), 140 | Movie(name: "Alien", director: "Ridley Scott") 141 | ] 142 | 143 | for movie in someObjects as! [Movie] { 144 | print("Movie: '\(movie.name)', dir. \(movie.director)") 145 | } 146 | 147 | 148 | /* 149 | === 150 | Any 151 | === 152 | */ 153 | 154 | 155 | var things = [Any]() 156 | 157 | things.append(0) 158 | things.append(0.0) 159 | things.append(42) 160 | things.append(3.14159) 161 | things.append("hello") 162 | things.append((3.0, 5.0)) 163 | things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) 164 | things.append({ (name: String) -> String in "Hello, \(name)" }) 165 | 166 | 167 | /* 168 | You can use the is and as operators in a switch statement’s cases to discover the specific type of a constant or variable 169 | that is known only to be of type Any or AnyObject. 170 | */ 171 | 172 | 173 | for thing in things { 174 | switch thing { 175 | case 0 as Int: 176 | print("zero as an Int") 177 | case 0 as Double: 178 | print("zero as a Double") 179 | case let someInt as Int: 180 | print("an integer value of \(someInt)") 181 | case let someDouble as Double where someDouble > 0: 182 | print("a positive double value of \(someDouble)") 183 | case is Double: // Here it's valid to use is, since the only thing being queried is the type. Other case statements store values in vars, so they use as. 184 | print("some other double value that I don't want to print") 185 | case let someString as String: 186 | print("a string value of \"\(someString)\"") 187 | case let (x, y) as (Double, Double): 188 | print("an (x, y) point at \(x), \(y)") 189 | case let movie as Movie: 190 | print("a movie called '\(movie.name)', dir. \(movie.director)") 191 | case let stringConverter as (String) -> String: 192 | print(stringConverter("Michael")) 193 | default: 194 | print("something else") 195 | } 196 | } -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/21 Extensions.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | Extensions add new functionality to an existing class, structure, enumeration, or protocol type. 17 | Extensions can add new functionality to a type, but they cannot override existing functionality. 18 | */ 19 | 20 | 21 | /* 22 | ================ 23 | Extension Syntax 24 | ================ 25 | */ 26 | 27 | extension Int/*: SomeProtocol, AnotherProtocol*/ { 28 | // new functionality to add to SomeType goes here 29 | // implementation of protocol requirements goes here 30 | } 31 | 32 | /* 33 | If you define an extension to add new functionality to an existing type, the new functionality will be 34 | available on all existing instances of that type, even if they were created before the extension was defined. 35 | */ 36 | 37 | 38 | /* 39 | =================== 40 | Computed Properties 41 | =================== 42 | */ 43 | 44 | // Extensions can add computed instance properties and computed type properties to existing types. 45 | 46 | extension Double { 47 | var km: Double { return self * 1_000.0 } 48 | var m: Double { return self } 49 | var cm: Double { return self / 100.0 } 50 | var mm: Double { return self / 1_000.0 } 51 | var ft: Double { return self / 3.28084 } 52 | } 53 | 54 | let oneInch = 25.4.mm 55 | print("One inch is \(oneInch) meters") 56 | // prints "One inch is 0.0254 meters" 57 | let threeFeet = 3.ft 58 | print("Three feet is \(threeFeet) meters") 59 | // prints "Three feet is 0.914399970739201 meters" 60 | 61 | /* 62 | Extensions can add new computed properties, but they cannot add stored properties, 63 | or add property observers to existing properties. 64 | */ 65 | 66 | 67 | /* 68 | ============ 69 | Initializers 70 | ============ 71 | */ 72 | 73 | /* 74 | Extensions can add new initializers to existing types. This enables you to extend other types to accept 75 | your own custom types as initializer parameters, or to provide additional initialization options that were not 76 | included as part of the type’s original implementation. 77 | 78 | Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers 79 | to a class. Designated initializers and deinitializers must always be provided by the original class implementation. 80 | */ 81 | 82 | struct Size { 83 | var width = 0.0, height = 0.0 84 | } 85 | struct Point { 86 | var x = 0.0, y = 0.0 87 | } 88 | struct Rect { 89 | var origin = Point() 90 | var size = Size() 91 | } 92 | 93 | let defaultRect = Rect() 94 | let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0), 95 | size: Size(width: 5.0, height: 5.0)) 96 | 97 | 98 | extension Rect { 99 | init(center: Point, size: Size) { 100 | let originX = center.x - (size.width / 2) 101 | let originY = center.y - (size.height / 2) 102 | self.init(origin: Point(x: originX, y: originY), size: size) 103 | } 104 | } 105 | 106 | let centerRect = Rect(center: Point(x: 4.0, y: 4.0), 107 | size: Size(width: 3.0, height: 3.0)) 108 | // centerRect's origin is (2.5, 2.5) and its size is (3.0, 3.0) 109 | 110 | 111 | /* 112 | If you provide a new initializer with an extension, you are still responsible for making sure that 113 | each instance is fully initialized once the initializer completes. 114 | */ 115 | 116 | 117 | /* 118 | ======= 119 | Methods 120 | ======= 121 | */ 122 | 123 | 124 | /* 125 | Extensions can add new instance methods and type methods to existing types. 126 | The following example adds a new instance method called repetitions to the Int type: 127 | */ 128 | 129 | extension Int { 130 | func repetitions(task: () -> Void) { 131 | for _ in 0.. Void, which indicates a 139 | function that has no parameters and does not return a value. 140 | */ 141 | 142 | 3.repetitions { 143 | print("Goodbye!") 144 | } 145 | 146 | 147 | /* 148 | ========================= 149 | Mutating Instance Methods 150 | ========================= 151 | */ 152 | 153 | /* 154 | Structure and enumeration methods that modify self or its properties must mark the 155 | instance method as mutating, just like mutating methods from an original implementation. 156 | */ 157 | 158 | extension Int { 159 | mutating func square() { 160 | self = self * self 161 | } 162 | } 163 | var someInt = 3 164 | someInt.square() 165 | // someInt is now 9 166 | 167 | 168 | /* 169 | ========== 170 | Subscripts 171 | ========== 172 | */ 173 | 174 | extension Int { 175 | subscript(digitIndex: Int) -> Int { 176 | var index = digitIndex 177 | var decimalBase = 1 178 | while index > 0 { 179 | decimalBase *= 10 180 | index -= 1 181 | } 182 | return (self / decimalBase) % 10 183 | } 184 | } 185 | 186 | 746381295[0] 187 | // returns 5 188 | 746381295[1] 189 | // returns 9 190 | 746381295[2] 191 | // returns 2 192 | 746381295[8] 193 | // returns 7 194 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/22 Protocols.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | =============== 17 | Protocol Syntax 18 | =============== 19 | */ 20 | 21 | protocol SomeProtocol { 22 | // protocol definition goes here 23 | } 24 | 25 | protocol AnotherProtocol { 26 | // protocol definition goes here 27 | } 28 | 29 | class SomeSuperclass { 30 | 31 | } 32 | 33 | //If a class has a superclass, list the superclass name before any protocols it adopts, followed by a comma. 34 | class SomeClass: SomeSuperclass, SomeProtocol, AnotherProtocol { 35 | // class definition goes here 36 | } 37 | 38 | /* 39 | ===================== 40 | Property Requirements 41 | ===================== 42 | */ 43 | 44 | /* If a protocol requires a property to be gettable and settable, that property requirement cannot be 45 | fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, 46 | the requirement can be satisfied by any kind of property, and it is valid for the property to be also settable if this is useful for your own code. 47 | */ 48 | 49 | protocol SomeOtherProtocol { 50 | var mustBeSettable: Int { get set } 51 | var doesNotNeedToBeSettable: Int { get } 52 | } 53 | 54 | protocol FullyNamed { 55 | var fullName: String { get } 56 | } 57 | 58 | // Here’s an example of a simple structure that adopts and conforms to the FullyNamed protocol. 59 | 60 | struct Person: FullyNamed { 61 | var fullName: String 62 | } 63 | let john = Person(fullName: "John Appleseed") 64 | 65 | class Starship: FullyNamed { 66 | var prefix: String? 67 | var name: String 68 | init(name: String, prefix: String? = nil) { 69 | self.name = name 70 | self.prefix = prefix 71 | } 72 | // Computed property. 73 | var fullName: String { 74 | return (prefix != nil ? prefix! + " " : "") + name 75 | } 76 | } 77 | var ncc1701 = Starship(name: "Enterprise", prefix: "USS") 78 | 79 | 80 | /* 81 | =================== 82 | Method Requirements 83 | =================== 84 | */ 85 | 86 | protocol RandomNumberGenerator { 87 | func random() -> Double 88 | } 89 | 90 | class LinearCongruentialGenerator: RandomNumberGenerator { 91 | var lastRandom = 42.0 92 | let m = 139_968.0 93 | let a = 3_877.0 94 | let c = 29_573.0 95 | func random() -> Double { 96 | lastRandom = ((lastRandom * a + c) .truncatingRemainder(dividingBy: m)) 97 | return lastRandom / m 98 | } 99 | } 100 | var generator = LinearCongruentialGenerator() 101 | print("Here's a random number: \(generator.random())") 102 | // prints "Here's a random number: 0.37464991998171" 103 | print("And another one: \(generator.random())") 104 | // prints "And another one: 0.729023776863283" 105 | 106 | 107 | /* 108 | ============================ 109 | Mutating Method Requirements 110 | ============================ 111 | */ 112 | 113 | /* 114 | If you define a protocol instance method requirement that is intended to mutate instances 115 | of any type that adopts the protocol, mark the method with the mutating keyword as part 116 | of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement. 117 | 118 | NOTE 119 | If you mark a protocol instance method requirement as mutating, you do not need to 120 | write the mutating keyword when writing an implementation of that method for a class. 121 | The mutating keyword is only used by structures and enumerations. 122 | */ 123 | 124 | protocol Togglable { 125 | mutating func toggle() 126 | } 127 | 128 | enum OnOffSwitch: Togglable { 129 | case Off, On 130 | mutating func toggle() { 131 | switch self { 132 | case Off: 133 | self = On 134 | case On: 135 | self = Off 136 | } 137 | } 138 | } 139 | var lightSwitch = OnOffSwitch.Off 140 | lightSwitch.toggle() 141 | // lightSwitch is now equal to .On 142 | 143 | 144 | /* 145 | ======================== 146 | Initializer Requirements 147 | ======================== 148 | */ 149 | 150 | protocol SomeNewProtocol { 151 | init(someParameter: Int) 152 | } 153 | 154 | /* 155 | You can implement a protocol initializer requirement on a conforming class as either a designated initializer 156 | or a convenience initializer. In both cases, you must mark the initializer implementation with the required modifier: 157 | */ 158 | 159 | class SomeNewClass: SomeNewProtocol { 160 | required init(someParameter: Int) { 161 | // initializer implementation goes here 162 | } 163 | } 164 | 165 | /* 166 | NOTE 167 | You do not need to mark protocol initializer implementations with the required modifier on classes 168 | that are marked with the final modifier, because final classes cannot be subclassed. For more on the final modifier, see Preventing Overrides. 169 | */ 170 | 171 | class SomeSuperClass { 172 | init() { 173 | // initializer implementation goes here 174 | } 175 | } 176 | 177 | class SomeSubClass: SomeSuperClass, SomeProtocol { 178 | // "required" from SomeProtocol conformance; "override" from SomeSuperClass 179 | required override init() { 180 | // initializer implementation goes here 181 | } 182 | } 183 | 184 | 185 | /* 186 | ================== 187 | Protocols as Types 188 | ================== 189 | */ 190 | 191 | /* 192 | Because it is a type, you can use a protocol in many places where other types are allowed, including: 193 | 194 | - As a parameter type or return type in a function, method, or initializer 195 | - As the type of a constant, variable, or property 196 | - As the type of items in an array, dictionary, or other container 197 | 198 | NOTE 199 | Because protocols are types, begin their names with a capital letter (such as FullyNamed and RandomNumberGenerator) to match the names of other types in Swift (such as Int, String, and Double). 200 | */ 201 | 202 | class Dice { 203 | let sides: Int 204 | let generator: RandomNumberGenerator 205 | init(sides: Int, generator: RandomNumberGenerator) { 206 | self.sides = sides 207 | self.generator = generator 208 | } 209 | func roll() -> Int { 210 | return Int(generator.random() * Double(sides)) + 1 211 | } 212 | } 213 | 214 | var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator()) 215 | for _ in 1...5 { 216 | print("Random dice roll is \(d6.roll())") 217 | } 218 | // Random dice roll is 3 219 | // Random dice roll is 5 220 | // Random dice roll is 4 221 | // Random dice roll is 5 222 | // Random dice roll is 4 223 | 224 | 225 | /* 226 | ========== 227 | Delegation 228 | ========== 229 | */ 230 | 231 | protocol DiceGame { 232 | var dice: Dice { get } 233 | func play() 234 | } 235 | protocol DiceGameDelegate { 236 | func gameDidStart(game: DiceGame) 237 | func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) 238 | func gameDidEnd(game: DiceGame) 239 | } 240 | 241 | class SnakesAndLadders: DiceGame { 242 | let finalSquare = 25 243 | let dice = Dice(sides: 6, generator: LinearCongruentialGenerator()) 244 | var square = 0 245 | var board: [Int] 246 | init() { 247 | board = [Int](repeating: 0, count: finalSquare + 1) 248 | board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 249 | board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 250 | } 251 | var delegate: DiceGameDelegate? 252 | func play() { 253 | square = 0 254 | delegate?.gameDidStart(game: self) 255 | gameLoop: while square != finalSquare { 256 | let diceRoll = dice.roll() 257 | delegate?.game(game: self, didStartNewTurnWithDiceRoll: diceRoll) 258 | switch square + diceRoll { 259 | case finalSquare: 260 | break gameLoop 261 | case let newSquare where newSquare > finalSquare: 262 | continue gameLoop 263 | default: 264 | square += diceRoll 265 | square += board[square] 266 | } 267 | } 268 | delegate?.gameDidEnd(game: self) 269 | } 270 | } 271 | 272 | /* 273 | Note that the delegate property is defined as an optional DiceGameDelegate, 274 | because a delegate isn’t required in order to play the game. Because it is of an optional type, 275 | the delegate property is automatically set to an initial value of nil. Thereafter, the game instantiator has the option to set the property to a suitable delegate. 276 | */ 277 | 278 | class DiceGameTracker: DiceGameDelegate { 279 | var numberOfTurns = 0 280 | func gameDidStart(game: DiceGame) { 281 | numberOfTurns = 0 282 | if game is SnakesAndLadders { 283 | print("Started a new game of Snakes and Ladders") 284 | } 285 | print("The game is using a \(game.dice.sides)-sided dice") 286 | } 287 | func game(game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) { 288 | numberOfTurns += 1 289 | print("Rolled a \(diceRoll)") 290 | } 291 | func gameDidEnd(game: DiceGame) { 292 | print("The game lasted for \(numberOfTurns) turns") 293 | } 294 | } 295 | 296 | // In action: 297 | 298 | let tracker = DiceGameTracker() 299 | let game = SnakesAndLadders() 300 | game.delegate = tracker 301 | game.play() 302 | 303 | /* 304 | ============================================= 305 | Adding Protocol Conformance with an Extension 306 | ============================================= 307 | */ 308 | 309 | 310 | /* 311 | You can extend an existing type to adopt and conform to a new protocol, 312 | even if you do not have access to the source code for the existing type. 313 | Extensions can add new properties, methods, and subscripts to an existing type, 314 | and are therefore able to add any requirements that a protocol may demand 315 | */ 316 | 317 | protocol TextRepresentable { 318 | var textualDescription: String { get } 319 | } 320 | 321 | extension Dice: TextRepresentable { 322 | var textualDescription: String { 323 | return "A \(sides)-sided dice" 324 | } 325 | } 326 | 327 | let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator()) 328 | print(d12.textualDescription) 329 | // prints "A 12-sided dice" 330 | 331 | /* Declaring Protocol Adoption with an Extension */ 332 | 333 | struct Hamster { 334 | var name: String 335 | var textualDescription: String { 336 | return "A hamster named \(name)" 337 | } 338 | } 339 | extension Hamster: TextRepresentable {} 340 | 341 | 342 | // Protocols can also be added to collections 343 | 344 | let simon = Hamster(name: "Simon") 345 | let things: [TextRepresentable] = [d12, simon] 346 | 347 | for thing in things { 348 | print(thing.textualDescription) 349 | } 350 | 351 | 352 | /* 353 | ==================== 354 | Protocol Inheritance 355 | ==================== 356 | */ 357 | 358 | protocol PrettyTextRepresentable: TextRepresentable { 359 | var prettyTextualDescription: String { get } 360 | } 361 | 362 | extension SnakesAndLadders: TextRepresentable { 363 | var textualDescription: String { 364 | return "A game of Snakes and Ladders with \(finalSquare) squares" 365 | } 366 | } 367 | 368 | extension SnakesAndLadders: PrettyTextRepresentable { 369 | var prettyTextualDescription: String { 370 | var output = textualDescription + ":\n" 371 | for index in 1...finalSquare { 372 | switch board[index] { 373 | case let ladder where ladder > 0: 374 | output += "▲ " 375 | case let snake where snake < 0: 376 | output += "▼ " 377 | default: 378 | output += "○ " 379 | } 380 | } 381 | return output 382 | } 383 | } 384 | 385 | /* 386 | This example defines a new protocol, PrettyTextRepresentable, which inherits from TextRepresentable. 387 | Anything that adopts PrettyTextRepresentable must satisfy all of the requirements enforced by TextRepresentable, 388 | plus the additional requirements enforced by PrettyTextRepresentable. 389 | */ 390 | 391 | 392 | /* 393 | ==================== 394 | Class-Only Protocols 395 | ==================== 396 | */ 397 | 398 | /* 399 | You can limit protocol adoption to class types (and not structures or enumerations) by adding the class keyword 400 | to a protocol’s inheritance list. The class keyword must always appear first in a protocol’s inheritance list, before any inherited protocols 401 | */ 402 | 403 | protocol SomeInheritedProtocol {} 404 | 405 | protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { 406 | // class-only protocol definition goes here 407 | } 408 | 409 | /* 410 | ==================== 411 | Protocol Composition 412 | ==================== 413 | */ 414 | 415 | /* 416 | It can be useful to require a type to conform to multiple protocols at once. 417 | You can combine multiple protocols into a single requirement with a protocol composition. 418 | Protocol compositions have the form protocol. 419 | You can list as many protocols within the pair of angle brackets (<>) as you need, separated by commas. 420 | */ 421 | 422 | protocol Named { 423 | var name: String { get } 424 | } 425 | protocol Aged { 426 | var age: Int { get } 427 | } 428 | struct Personn: Named, Aged { 429 | var name: String 430 | var age: Int 431 | } 432 | func wishHappyBirthday(celebrator: protocol) { 433 | print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!") 434 | } 435 | let birthdayPerson = Personn(name: "Malcolm", age: 21) 436 | wishHappyBirthday(celebrator: birthdayPerson) 437 | // prints "Happy birthday Malcolm - you're 21!" 438 | 439 | /* 440 | NOTE 441 | 442 | Protocol compositions do not define a new, permanent protocol type. 443 | Rather, they define a temporary local protocol that has the combined requirements of all protocols in the composition. 444 | */ 445 | 446 | 447 | /* 448 | ================================= 449 | Checking for Protocol Conformance 450 | ================================= 451 | */ 452 | 453 | /* 454 | You can use the is and as operators described in Type Casting to check for protocol conformance, 455 | and to cast to a specific protocol. Checking for and casting to a protocol follows exactly the same syntax 456 | as checking for and casting to a type: 457 | 458 | • The is operator returns true if an instance conforms to a protocol and returns false if it does not. 459 | • The as? version of the downcast operator returns an optional value of the protocol’s type, and this value is nil if the instance does not conform to that protocol. 460 | • The as! version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast does not succeed. 461 | */ 462 | 463 | 464 | /* 465 | ============================== 466 | Optional Protocol Requirements 467 | ============================== 468 | */ 469 | 470 | /* 471 | Optional requirements are prefixed by the optional modifier as part of the protocol’s definition. 472 | When you use a method or property in an optional requirement, its type automatically becomes an optional. 473 | For example, a method of type (Int) -> String becomes ((Int) -> String)?. Note that the entire function type is wrapped in the optional, not method’s the return value. 474 | 475 | You check for an implementation of an optional method by writing a question mark after the name of the method when it is called, such as someOptionalMethod?(someArgument). 476 | 477 | 478 | NOTE 479 | 480 | Optional protocol requirements can only be specified if your protocol is marked with the @objc attribute. 481 | 482 | This attribute indicates that the protocol should be exposed to Objective-C code and is described in 483 | Using Swift with Cocoa and Objective-C (Swift 2.1). Even if you are not interoperating with Objective-C, 484 | you need to mark your protocols with the @objc attribute if you want to specify optional requirements. 485 | 486 | Note also that @objc protocols can be adopted only by classes that inherit from 487 | Objective-C classes or other @objc classes. They can’t be adopted by structures or enumerations. 488 | */ 489 | 490 | @objc protocol CounterDataSource { 491 | @objc optional func incrementForCount(count: Int) -> Int 492 | @objc optional var fixedIncrement: Int { get } 493 | } 494 | 495 | class Counter { 496 | var count = 0 497 | var dataSource: CounterDataSource? 498 | func increment() { 499 | if let amount = dataSource?.incrementForCount?(count: count) { 500 | count += amount 501 | } else if let amount = dataSource?.fixedIncrement { 502 | count += amount 503 | } 504 | } 505 | } 506 | 507 | /* 508 | Because the call to incrementForCount(_:) can fail for either of these two reasons, 509 | the call returns an optional Int value. This is true even though incrementForCount(_:) 510 | is defined as returning a nonoptional Int value in the definition of CounterDataSource. 511 | */ 512 | 513 | 514 | /* 515 | =================== 516 | Protocol Extensions 517 | =================== 518 | */ 519 | 520 | extension RandomNumberGenerator { 521 | func randomBool() -> Bool { 522 | return random() > 0.5 523 | } 524 | } 525 | 526 | // By creating an extension on the protocol, all conforming types automatically gain this method implementation without any additional modification. 527 | 528 | generator = LinearCongruentialGenerator() 529 | print("Here's a random number: \(generator.random())") 530 | // prints "Here's a random number: 0.37464991998171" 531 | print("And here's a random Boolean: \(generator.randomBool())") 532 | // prints "And here's a random Boolean: true" 533 | 534 | 535 | /* 536 | You can use protocol extensions to provide a default implementation to any method or property requirement of that protocol. 537 | If a conforming type provides its own implementation of a required method or property, 538 | that implementation will be used instead of the one provided by the extension. 539 | 540 | NOTE 541 | 542 | Protocol requirements with default implementations provided by extensions are distinct from optional protocol requirements. 543 | Although conforming types don’t have to provide their own implementation of either, 544 | requirements with default implementations can be called without optional chaining. 545 | */ 546 | 547 | /* 548 | When you define a protocol extension, you can specify constraints that conforming types must satisfy 549 | before the methods and properties of the extension are available. You write these constraints 550 | after the name of the protocol you’re extending using a where clause 551 | */ 552 | 553 | extension Collection where Iterator.Element: TextRepresentable { 554 | var textualDescription: String { 555 | let itemsAsText = self.map { $0.textualDescription } 556 | return "[" + itemsAsText.joined(separator: ", ") + "]" 557 | } 558 | } 559 | 560 | let murrayTheHamster = Hamster(name: "Murray") 561 | let morganTheHamster = Hamster(name: "Morgan") 562 | let mauriceTheHamster = Hamster(name: "Maurice") 563 | let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster] 564 | 565 | // Because Array conforms to CollectionType and the array’s elements conform to the TextRepresentable protocol, 566 | // the array can use the textualDescription property to get a textual representation of its contents. 567 | 568 | print(hamsters.textualDescription) 569 | // prints "[A hamster named Murray, A hamster named Morgan, A hamster named Maurice]" 570 | 571 | /* 572 | NOTE 573 | 574 | If a conforming type satisfies the requirements for multiple constrained extensions that provide implementations 575 | for the same method or property, Swift will use the implementation corresponding to the most specialized constraints. 576 | */ 577 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Pages/23 Generics.xcplaygroundpage/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | // |=------------------------------------------------------=| 3 | // Copyright (c) 2016 Juan Antonio Karmy. 4 | // Licensed under MIT License 5 | // 6 | // See https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ for Swift Language Reference 7 | // 8 | // See Juan Antonio Karmy - http://karmy.co | http://twitter.com/jkarmy 9 | // 10 | // |=------------------------------------------------------=| 11 | 12 | 13 | import UIKit 14 | 15 | /* 16 | ================= 17 | Generic Functions 18 | ================= 19 | */ 20 | 21 | // Basic example 22 | 23 | func swapTwoValues( _ a: inout T, _ b: inout T) { 24 | let temporaryA = a 25 | a = b 26 | b = temporaryA 27 | } 28 | 29 | var someInt = 3 30 | var anotherInt = 107 31 | swapTwoValues(&someInt, &anotherInt) 32 | // someInt is now 107, and anotherInt is now 3 33 | 34 | var someString = "hello" 35 | var anotherString = "world" 36 | swapTwoValues(&someString, &anotherString) 37 | // someString is now "world", and anotherString is now "hello" 38 | 39 | /* 40 | The swapTwoValues(_:_:) function defined above is inspired by a generic function called swap, 41 | which is part of the Swift standard library, and is automatically made available for you to use in your apps. 42 | If you need the behavior of the swapTwoValues(_:_:) function in your own code, you can use Swift’s 43 | existing swap(_:_:) function rather than providing your own implementation. 44 | */ 45 | 46 | /*You can provide more than one type parameter by writing multiple type parameter names within the angle brackets, separated by commas.*/ 47 | 48 | /* 49 | ====================== 50 | Naming Type Parameters 51 | ====================== 52 | */ 53 | 54 | /* 55 | In most cases, type parameters have descriptive names, such as Key and Value in Dictionary 56 | and Element in Array, which tells the reader about the relationship between the type parameter 57 | and the generic type or function it’s used in. However, when there isn’t a meaningful relationship between them, 58 | it’s traditional to name them using single letters such as T, U, and V, such as T in the swapTwoValues(_:_:) function above. 59 | */ 60 | 61 | /* 62 | NOTE 63 | 64 | Always give type parameters upper camel case names (such as T and MyTypeParameter) to indicate 65 | that they are a placeholder for a type, not a value. 66 | */ 67 | 68 | 69 | /* 70 | ============= 71 | Generic Types 72 | ============= 73 | */ 74 | 75 | /* 76 | Swift enables you to define your own generic types. These are custom classes, structures, 77 | and enumerations that can work with any type, in a similar way to Array and Dictionary. 78 | */ 79 | 80 | struct Stack { 81 | var items = [Element]() 82 | mutating func push(item: Element) { 83 | items.append(item) 84 | } 85 | mutating func pop() -> Element { 86 | return items.removeLast() 87 | } 88 | } 89 | 90 | /* 91 | Note how the generic version of Stack is essentially the same as the non-generic version, 92 | but with a type parameter called Element instead of an actual type of Int. 93 | This type parameter is written within a pair of angle brackets () immediately after the structure’s name. 94 | 95 | Element defines a placeholder name for “some type Element” to be provided later on. 96 | This future type can be referred to as “Element” anywhere within the structure’s definition. 97 | */ 98 | 99 | var stackOfStrings = Stack() 100 | stackOfStrings.push(item: "uno") 101 | stackOfStrings.push(item: "dos") 102 | stackOfStrings.push(item: "tres") 103 | stackOfStrings.push(item: "cuatro") 104 | // the stack now contains 4 strings 105 | 106 | 107 | /* 108 | ======================== 109 | Extending a Generic Type 110 | ======================== 111 | */ 112 | 113 | /* 114 | When you extend a generic type, you do not provide a type parameter list as part of the extension’s definition. 115 | Instead, the type parameter list from the original type definition is available within the body of the extension, 116 | and the original type parameter names are used to refer to the type parameters from the original definition. 117 | */ 118 | 119 | extension Stack { 120 | var topItem: Element? { 121 | return items.isEmpty ? nil : items[items.count - 1] 122 | } 123 | } 124 | 125 | /* 126 | Note that this extension does not define a type parameter list. 127 | Instead, the Stack type’s existing type parameter name, Element, 128 | is used within the extension to indicate the optional type of the topItem computed property. 129 | */ 130 | 131 | 132 | /* 133 | ================ 134 | Type Constraints 135 | ================ 136 | */ 137 | 138 | protocol SomeProtocol { 139 | 140 | } 141 | 142 | class SomeClass { 143 | 144 | } 145 | 146 | func someFunction(someT: T, someU: U) { 147 | // function body goes here 148 | } 149 | 150 | /* 151 | The hypothetical function above has two type parameters. The first type parameter, T, 152 | has a type constraint that requires T to be a subclass of SomeClass. 153 | The second type parameter, U, has a type constraint that requires U to conform to the protocol SomeProtocol. 154 | */ 155 | 156 | // Example 157 | func findIndex(array: [T], _ valueToFind: T) -> Int? { 158 | for (index, value) in array.enumerated() { 159 | if value == valueToFind { 160 | return index 161 | } 162 | } 163 | return nil 164 | } 165 | 166 | /* 167 | ================ 168 | Associated Types 169 | ================ 170 | */ 171 | 172 | /* 173 | The Container protocol needs a way to refer to the type of the elements that a container will hold, 174 | without knowing what that type is for a specific container. 175 | */ 176 | 177 | protocol Container { 178 | associatedtype ItemType 179 | mutating func append(item: ItemType) 180 | var count: Int { get } 181 | subscript(i: Int) -> ItemType { get } 182 | } 183 | 184 | struct OtherStack: Container { 185 | // original Stack implementation 186 | var items = [Element]() 187 | mutating func push(item: Element) { 188 | items.append(item) 189 | } 190 | mutating func pop() -> Element { 191 | return items.removeLast() 192 | } 193 | // conformance to the Container protocol 194 | mutating func append(item: Element) { 195 | self.push(item: item) 196 | } 197 | var count: Int { 198 | return items.count 199 | } 200 | subscript(i: Int) -> Element { 201 | return items[i] 202 | } 203 | } 204 | 205 | /* 206 | Thanks to Swift’s type inference, you don’t actually need to declare a concrete ItemType of Int as part of the definition of IntStack. 207 | Because IntStack conforms to all of the requirements of the Container protocol, Swift can infer the appropriate ItemType to use, 208 | simply by looking at the type of the append(_:) method’s item parameter and the return type of the subscript. 209 | Indeed, if you delete the typealias ItemType = Int line from the code above, 210 | everything still works, because it is clear what type should be used for ItemType. 211 | */ 212 | 213 | // You can extend an existing type to add conformance to a protocol. 214 | 215 | extension Array: Container {} 216 | 217 | /* 218 | ================ 219 | Associated Types 220 | ================ 221 | */ 222 | 223 | func allItemsMatch< 224 | C1: Container, C2: Container 225 | where C1.ItemType == C2.ItemType, C1.ItemType: Equatable> 226 | (someContainer: C1, _ anotherContainer: C2) -> Bool { 227 | 228 | // check that both containers contain the same number of items 229 | if someContainer.count != anotherContainer.count { 230 | return false 231 | } 232 | 233 | // check each pair of items to see if they are equivalent 234 | for i in 0.. (SomeInternalClass, SomePrivateClass) { 211 | // function implementation goes here 212 | return (SomeInternalClass(), SomePrivateClass()) 213 | } 214 | 215 | /* 216 | Enumeration Types 217 | ----------------- 218 | 219 | The individual cases of an enumeration automatically receive the same access level as the enumeration they belong to. 220 | You cannot specify a different access level for individual enumeration cases. 221 | */ 222 | 223 | /* 224 | ========== 225 | Subclasses 226 | ========== 227 | */ 228 | 229 | /* 230 | You can subclass any class that can be accessed in the current access context. 231 | A subclass cannot have a higher access level than its superclass—for example, 232 | you cannot write a public subclass of an internal superclass. 233 | 234 | In addition, you can override any class member (method, property, initializer, or subscript) that is visible in a certain access context. 235 | An override can make an inherited class member more accessible than its superclass version. 236 | 237 | It is even valid for a subclass member to call a superclass member that has lower access permissions than the subclass member, 238 | as long as the call to the superclass’s member takes place within an allowed access level context 239 | */ 240 | 241 | public class A { 242 | private func someMethod() {} 243 | } 244 | 245 | internal class B: A { 246 | override internal func someMethod() { 247 | super.someMethod() 248 | } 249 | } 250 | 251 | // Because superclass A and subclass B are defined in the same source file, 252 | // it is valid for the B implementation of someMethod() to call super.someMethod(). 253 | 254 | 255 | /* 256 | ================================================ 257 | Constants, Variables, Properties, and Subscripts 258 | ================================================ 259 | */ 260 | 261 | // A constant, variable, or property cannot be more public than its type. 262 | // It is not valid to write a public property with a private type, for example. 263 | // Similarly, a subscript cannot be more public than either its index type or return type. 264 | 265 | /* Getters and Setters 266 | ------------------- 267 | 268 | Getters and setters for constants, variables, properties, 269 | and subscripts automatically receive the same access level as the 270 | constant, variable, property, or subscript they belong to. 271 | 272 | You can give a setter a lower access level than its corresponding getter, 273 | to restrict the read-write scope of that variable, property, or subscript. 274 | You assign a lower access level by writing private(set) or internal(set) before the var or subscript introducer. 275 | */ 276 | 277 | struct TrackedString { 278 | private(set) var numberOfEdits = 0 279 | var value: String = "" { 280 | didSet { 281 | numberOfEdits += 1 282 | } 283 | } 284 | } 285 | 286 | /* 287 | The access level for the numberOfEdits property is marked with a private(set) modifier 288 | to indicate that the property should be settable only from within the same source file 289 | as the TrackedString structure’s definition. The property’s getter still has the default access level of internal, 290 | but its setter is now private to the source file in which TrackedString is defined. 291 | This enables TrackedString to modify the numberOfEdits property internally, 292 | but to present the property as a read-only property when it is used by other source files within the same module. 293 | 294 | You can make the structure’s numberOfEdits property getter public, and its property setter private, 295 | by combining the public and private(set) access level modifiers: 296 | */ 297 | 298 | public private(set) var numberOfEdits = 0 299 | 300 | 301 | /* 302 | ============ 303 | Initializers 304 | ============ 305 | */ 306 | 307 | /* 308 | Custom initializers can be assigned an access level less than or equal to the type that they initialize. 309 | As with function and method parameters, the types of an initializer’s parameters cannot be 310 | more private than the initializer’s own access level. 311 | */ 312 | 313 | /* 314 | Default Initializers 315 | -------------------- 316 | 317 | A default initializer has the same access level as the type it initializes, 318 | unless that type is defined as public. For a type that is defined as public, 319 | the default initializer is considered internal. 320 | If you want a public type to be initializable with a no-argument initializer when used in another module, 321 | you must explicitly provide a public no-argument initializer yourself as part of the type’s definition. 322 | */ 323 | 324 | 325 | /* 326 | ========= 327 | Protocols 328 | ========= 329 | */ 330 | 331 | /* 332 | If you want to assign an explicit access level to a protocol type, do so at the point that you define the protocol. 333 | This enables you to create protocols that can only be adopted within a certain access context. 334 | 335 | The access level of each requirement within a protocol definition is automatically set to the same access level as the protocol. 336 | You cannot set a protocol requirement to a different access level than the protocol it supports. 337 | This ensures that all of the protocol’s requirements will be visible on any type that adopts the protocol. 338 | */ 339 | 340 | /* 341 | Protocol Inheritance 342 | -------------------- 343 | 344 | If you define a new protocol that inherits from an existing protocol, 345 | the new protocol can have at most the same access level as the protocol it inherits from. 346 | You cannot write a public protocol that inherits from an internal protocol, for example. 347 | */ 348 | 349 | /* 350 | Protocol Conformance 351 | -------------------- 352 | 353 | When you write or extend a type to conform to a protocol, you must ensure that the type’s implementation of each protocol requirement 354 | has at least the same access level as the type’s conformance to that protocol. 355 | For example, if a public type conforms to an internal protocol, the type’s implementation of each protocol requirement must be at least “internal”. 356 | */ 357 | 358 | 359 | /* 360 | ========== 361 | Extensions 362 | ========== 363 | */ 364 | 365 | /* 366 | Any type members added in an extension have the same default access level as type members declared in the original type being extended. 367 | If you extend a public or internal type, any new type members you add will have a default access level of internal. 368 | If you extend a private type, any new type members you add will have a default access level of private. 369 | 370 | Alternatively, you can mark an extension with an explicit access level modifier (for example, private extension) 371 | to set a new default access level for all members defined within the extension. 372 | This new default can still be overridden within the extension for individual type members. 373 | */ 374 | 375 | /* 376 | Adding Protocol Conformance with an Extension 377 | --------------------------------------------- 378 | 379 | The protocol’s own access level is used to provide the default access level for each protocol requirement implementation within the extension. 380 | */ 381 | 382 | 383 | /* 384 | ========== 385 | Extensions 386 | ========== 387 | */ 388 | 389 | /* 390 | The access level for a generic type or generic function is the minimum of the access level 391 | of the generic type or function itself and the access level of any type constraints on its type parameters. 392 | */ 393 | 394 | 395 | /* 396 | ============ 397 | Type Aliases 398 | ============ 399 | */ 400 | 401 | /* 402 | A type alias can have an access level less than or equal to the access level of the type it aliases. 403 | For example, a private type alias can alias a private, internal, or public type, 404 | but a public type alias cannot alias an internal or private type. 405 | */ 406 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Resources/Higher Order Functions.playground/Contents.swift: -------------------------------------------------------------------------------- 1 | 2 | /*: 3 | [Previous](@previous) | [Next](@next) 4 | **** 5 | 6 | Copyright (c) 2016 Juan Antonio Karmy. 7 | Licensed under MIT License 8 | 9 | Official Apple documentation available at [Swift Language Reference](https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/) 10 | 11 | See Juan Antonio Karmy - [karmy.co](http://karmy.co) | [@jkarmy](http://twitter.com/jkarmy) 12 | 13 | **** 14 | */ 15 | 16 | //: Page created by Tien Vu - https://github.com/Tj3n 17 | 18 | /*: 19 | # HIGH ORDER FUNCTIONS 20 | */ 21 | 22 | import UIKit 23 | 24 | var array = [1,2,3,4,5] 25 | 26 | //: Map: Manipulate each value in the array. They can have a different value or type. 27 | let mapped = array.map { (value) -> Int in 28 | return value + 1 29 | } 30 | 31 | let mappedShort = array.map({ $0 + 1 }) 32 | mappedShort 33 | 34 | //: This can be written like this since we are passing a Trailing Closure. See the Closures chapter for further information. 35 | let mappedShort1 = array.map { $0 + 1 } 36 | mappedShort1 37 | 38 | 39 | //: Filter: each value in array must pass a rule to append itself into a newly made array 40 | let filtered = array.filter { (value) -> Bool in 41 | return value >= 4 42 | } 43 | 44 | let filteredShort = array.filter({ $0 >= 4 }) 45 | filteredShort 46 | 47 | let filteredShort1 = array.filter { $0 >= 4 } 48 | filteredShort1 49 | 50 | 51 | //: Reduce: combining the elements of an array to a single value 52 | 53 | // 0 is starting value 54 | let reduced = array.reduce(0) { (value1, value2) -> Int in 55 | value1 + value2 56 | } 57 | 58 | let reducedShort0 = array.reduce(0, ({ $0 + $1 })) 59 | reducedShort0 60 | 61 | let reducedShort1 = array.reduce(0) { $0 + $1 } 62 | reducedShort1 63 | 64 | let reducedShortest = array.reduce(0, +) 65 | reducedShortest 66 | 67 | // "test" is the starting value 68 | let reducedShort2 = array.reduce("test", ({ "\($0)\($1)"})) 69 | reducedShort2 70 | 71 | // Mathematics functions can be used 72 | let reducedShorter = array.reduce(1, *) 73 | 74 | 75 | //: Flatmap: supports optionals and squence of sequence 76 | var multidimentionalArray: [[Int]?] = [[1,2], [3,5], [4], nil] 77 | 78 | let flatmapped: [[Int]?] = multidimentionalArray.flatMap { (array) in 79 | return array != nil && array!.count > 1 ? array : [] 80 | } 81 | 82 | let flatmappedShort = multidimentionalArray.flatMap({ $0 }) //Remove nil 83 | flatmappedShort 84 | 85 | let flatmappedShort1 = multidimentionalArray.flatMap { $0 } //Remove nil 86 | flatmappedShort1 87 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Resources/Higher Order Functions.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/Resources/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Juan Antonio Karmy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /The Swift Summary Book.playground/contents.xcplayground: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /swift_brand_logo.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | --------------------------------------------------------------------------------