Repository: danielpi/Swift-Playgrounds Branch: master Commit: eae601fb7a63 Files: 139 Total size: 265.8 KB Directory structure: gitextract_qixja4zh/ ├── .gitignore ├── LICENSE ├── README.md ├── Swift-Playgrounds/ │ ├── Blogs/ │ │ ├── 2014-08-08-LockingInSwift.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── NSHipster/ │ │ │ └── 2014-08-18-SwiftLiteralConvertibles.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ └── Swift Blog/ │ │ ├── 2014-07-23-AccessControl.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── 2014-07-28-InteractingWithCPointers.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── 2014-08-05-Boolean.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── 2014-08-15-ValueAndReferenceTypes.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ └── 2014-08-27-OptionalCaseStudy-valuesForKeys.playground/ │ │ ├── contents.xcplayground │ │ ├── section-1.swift │ │ └── timeline.xctimeline │ ├── Info.plist │ ├── Others/ │ │ ├── 2014-08-11-SwiftOperators.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── Cheryls-Birthday-Alternative-1.playground/ │ │ │ ├── Contents.swift │ │ │ ├── Sources/ │ │ │ │ └── SupportCode.swift │ │ │ └── contents.xcplayground │ │ ├── Cheryls-Birthday.playground/ │ │ │ ├── Contents.swift │ │ │ ├── Sources/ │ │ │ │ └── SupportCode.swift │ │ │ └── contents.xcplayground │ │ └── WritingSwiftClassesWithObjectiveCBehaviour.playground/ │ │ ├── contents.xcplayground │ │ ├── section-1.swift │ │ └── timeline.xctimeline │ ├── Specific Technologies/ │ │ └── SpriteKit/ │ │ ├── GameDevUniversity.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ └── SpriteKitTestbed.playground/ │ │ ├── Contents.swift │ │ ├── Sources/ │ │ │ └── SupportCode.swift │ │ └── contents.xcplayground │ ├── Swift Stanard Library/ │ │ ├── Array.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── Dictionary.playground/ │ │ │ ├── contents.xcplayground │ │ │ └── section-1.swift │ │ ├── FreeFunctions.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── NumericTypes.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── Protocols.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── String.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ └── Undocumented.playground/ │ │ ├── contents.xcplayground │ │ ├── section-1.swift │ │ └── timeline.xctimeline │ ├── The Swift Programming Language/ │ │ ├── ASwiftTour.playground/ │ │ │ ├── Contents.swift │ │ │ ├── contents.xcplayground │ │ │ └── timeline.xctimeline │ │ └── LanguageGuide/ │ │ ├── 01-TheBasics.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 02-BasicOperators.playground/ │ │ │ ├── Contents.swift │ │ │ ├── contents.xcplayground │ │ │ └── timeline.xctimeline │ │ ├── 03-StringsAndCharacters.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 04-CollectionTypes.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 05-ControlFlow.playground/ │ │ │ ├── Contents.swift │ │ │ ├── contents.xcplayground │ │ │ └── timeline.xctimeline │ │ ├── 06-Functions.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 07-Closures.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 08-Enumerations.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 09-ClassesAndStructures.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 10-Properties.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 11-Methods.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 12-Subscripts.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 13-Inheritance.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 14-Initialization.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 15-Deinitialization.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 16-AutomaticReferenceCounting.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 17-OptionalChaining.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 18-ErrorHandling.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 19-TypeCasting.playground/ │ │ │ ├── contents.xcplayground │ │ │ └── section-1.swift │ │ ├── 20-NestedTypes.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 21-Extensions.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 22-Protocols.playground/ │ │ │ ├── contents.xcplayground │ │ │ └── section-1.swift │ │ ├── 23-Generics.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ ├── 24-AccessControl.playground/ │ │ │ ├── Contents.swift │ │ │ └── contents.xcplayground │ │ └── 25-AdvancedOperators.playground/ │ │ ├── contents.xcplayground │ │ ├── section-1.swift │ │ └── timeline.xctimeline │ ├── Using Swift With Cocoa And Objective-C/ │ │ ├── AdoptingCocoaDesignPatterns.playground/ │ │ │ ├── contents.xcplayground │ │ │ └── section-1.swift │ │ ├── BasicSetup.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── InteractingWithC-APIs.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ ├── InteractingWithObjective-C-APIs.playground/ │ │ │ ├── contents.xcplayground │ │ │ └── section-1.swift │ │ ├── Mix&Match.playground/ │ │ │ ├── contents.xcplayground │ │ │ ├── section-1.swift │ │ │ └── timeline.xctimeline │ │ └── WorkingWithCocoaDataTypes.playground/ │ │ ├── contents.xcplayground │ │ └── section-1.swift │ ├── WWDC/ │ │ └── 2014/ │ │ └── AdvancedSwift.playground/ │ │ ├── Contents.swift │ │ └── contents.xcplayground │ └── main.swift ├── Swift-Playgrounds.xcodeproj/ │ └── project.pbxproj └── Thoughts-Questions.txt ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Xcode .DS_Store build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 *.xcworkspace !default.xcworkspace xcuserdata profile *.moved-aside DerivedData .idea/ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2014 Daniel Pink Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ # Swift Playgrounds Some experiments with Playgrounds in XCode 8.2 using the Swift programming language. ## The Swift Programming Language Book I have been working through all the examples in the book Apple Inc. “The Swift Programming Language.” iBooks. https://itunes.apple.com/au/book/swift-programming-language/id881256329?mt=11. Each .playground file in the project relates to a chapter from the Swift Programming Language book. I have implemented this as a single XCode project that contains a playground file for each chapter of the language reference book. I'm finding it quite useful to have this project open when I am writing Swift code as I can use the project wide search functionality to lookup any Swift features or syntax that I am unsure about (so long as I can remember the words to look for) Below is a list of each of the files within the project (this is also a list of the chapters of the book that I have worked through). - **A Swift Tour** contains the code from the "Swift Tour" chapter. It touches on most of the unusual features of the language and is easy to search through to find examples. It is a large file and does tend to give the swift interpreter a rather hard time. Chapters from the Language guide. Each chapter goes into depth about its particular subject. - **The Basics** This chapter covers basic value types like Strings, Ints, Bools and floats. The notation for exponent values in float literals is interesting. Comments are covered (nested /* */ comment blocks). TypeAlias is covered as are tuples. Optionals are touched on and assertions are mentioned. - **Basic Operators** Arithmetic, remainder, increment, decrement, comparison, unary, ternary, range (closed and half-closed) and logical operators. There are examples of all of them. - **Strings And Characters** Some details about Unicode literals (multi-byte characters). The countElements() function for finding the length of a string. Concatenating strings, Comparing strings and Interpolating strings (not much on splitting or parsing strings). - **Collection Types** - **ControlFlow** - **Functions** - **Closures** - **Enumerations** - **Classes And Structures** - **Properties** - **Methods** - **Subscripts** - **Inheritance** - **Initialization** - **Deinitialization** - **Automatic Reference Counting** - **Optional Chaining** - **Type Casting** - **Nested Types** - **Extensions** - **Protocols** - **Generics** - **Advanced Operators** ## Using Swift with Cocoa and Objective-C Book There are six playground files that work through the code in the “Using Swift with Cocoa and Objective-C.” iBook. https://itunes.apple.com/au/book/using-swift-cocoa-objective/id888894773?mt=11. They are listed below. The example from this book didn't translate as well to the playgrounds as the previous book examples did. - **Basic Setup** - **Interacting With Objective-C-** - **Writing Classes With Objective C Behaviour** - **Working With Cocoa Data Types** - **Adopting Cocoa Design Patterns** - **InteractingWith C** ## Swift Standard Library The documentation for the Swift Standard Library can be found at the following link https://developer.apple.com/library/prerelease/ios/documentation/General/Reference/SwiftStandardLibraryReference/. There is a wealth of information contained in the standard library doc and it is nicely organised so that it is easy to experiment with in a playground environment. I have attempted to extend the examples somewhat to try and show off some of the other features of the standard library. - **String** - **Array** - **Dictionary** - **NumericTypes** - **Protocols** - **FreeFunctions** - **Undocumented** ## Swift Blog The Swift blog contains several articles detailing interesting information about the developing language. - **2014-08-15 Value and Reference Types** - **2014-08-05 Boolean** - **2014-07-28 Interacting with C Pointers** - **2014-07-23 Access Control** ## NSHipster Lots of great articles delving into the finer points of Cocoa programming. The recent articles on Swift are always interesting to go through - **2014-08-08 Swift Literal Convertibles** Shows how you can create types of your own that can be written as literals when you use them. # What next? Here are some links to other projects around the web that I would also like to implement - **Peter Norvig** has some great posts that delve into various programming topics. Mostly they are in Python though so it would be interesting to implement them in Swift. - http://norvig.com/spell-correct.html http://airspeedvelocity.net/2015/05/02/spelling/ - http://nbviewer.ipython.org/url/norvig.com/ipython/TSPv3.ipynb - **Erica Sandun** Has a book out and also publishes a lot of information about Swift Playgrounds. In particular she is able to get impressive graphics, windows and user inputs to work, which is something that I haven't figured out yet. - http://ericasadun.com/2015/05/04/swift-using-functions-to-initialize-view-types/ ================================================ FILE: Swift-Playgrounds/Blogs/2014-08-08-LockingInSwift.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/2014-08-08-LockingInSwift.playground/section-1.swift ================================================ // Locking in Swift blog post by John Gallagher // http://www.bignerdranch.com/blog/locking-in-swift-helping-protect-me-from-myself/ import Cocoa import Foundation import dispatch // The Setup // Writing a class that includes an array of things and a timestamp of when the array was last modified. /* class ArrayTracker { private var things: [T] = [] private var lastModified: NSDate? // Why is this optional? func appendToThings(item: T) -> (NSDate, Int) { things.append(item) lastModified = NSDate.date() return (lastModified!, things.count) } func lastModifiedDate() -> NSDate? { return lastModified } } var a: ArrayTracker = ArrayTracker() let (l1, c1) = a.appendToThings(1234) l1 c1 a.appendToThings(5678) a.appendToThings(4) */ /* // The Lock // We want a readers-writer lock. Multiple readers can access the lock concurrently but only a single writer can have access at a time. protocol ReadWriteLock { // Get a shared reader lock, run the given block, and unlock mutating func withReadLock(block: () -> ()) // get an exclusive writer lock, run the given block, and unlock mutating func withWriteLock(block: () -> ()) } struct MyLock: ReadWriteLock { let queue = dispatch_queue_create("readWriteLock", dispatch.DISPATCH_QUEUE_CONCURRENT) mutating func withReadLock(block: () -> ()) { dispatch_async(queue, block) } mutating func withWriteLock(block: () -> ()) { dispatch_barrier_async(queue, block) } } class ArrayTracker { private var things: [T] = [] private var lock: ReadWriteLock = MyLock() private var lastModified: NSDate? func lastModifiedDate() -> NSDate? { var date: NSDate? // withReadLock runs the block its given synchronously, so we don't need to capture self - use unowned lock.withReadLock { [unowned self] in date = self.lastModified } return date } func appendToThings(item: T) -> (NSDate, Int) { var date: NSDate! var count: Int! lock.withWriteLock { [unowned self] in self.things.append(item) self.lastModified = NSDate.date() date = self.lastModified count = self.things.count } return (date, count) } } */ let address = 0xFFFE address % 0xFFFF protocol ReadWriteLock { // Get a shared reader lock, run the given block, unlock, and return whatever the block returned mutating func withReadLock(block: () -> T) -> T // Get an exclusive writer lock, run the given block, unlock, and return whatever the block returned mutating func withWriteLock(block: () -> T) -> T } /* struct MyLock: ReadWriteLock { let queue = dispatch_queue_create("readWriteLock", dispatch.DISPATCH_QUEUE_CONCURRENT) mutating func withReadLock(block: () -> T) -> T { var result: T dispatch_sync(queue) { result = block() } return result } mutating func withWriteLock(block: () -> T) -> T { var result: T dispatch_barrier_sync(queue) { result = block() } return result } } class ArrayTracker { private var things: [T] = [] private var lock: ReadWriteLock = MyLock() private var lastModified: NSDate? func lastModifiedDate() -> NSDate? { // return the result of the call to withReadLock... return lock.withReadLock { [unowned self] in // ... which is the date that we want return self.lastModified } } func appendToThings(item: T) -> (NSDate, Int) { return lock.withWriteLock { [unowned self] in self.things.append(item) self.lastModified = NSDate.date() return (self.lastModified!, self.things.count) } } } */ ================================================ FILE: Swift-Playgrounds/Blogs/2014-08-08-LockingInSwift.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/NSHipster/2014-08-18-SwiftLiteralConvertibles.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/NSHipster/2014-08-18-SwiftLiteralConvertibles.playground/section-1.swift ================================================ // Swift Literal Convertibles from NSHipster http://nshipster.com/swift-literal-convertible/ import Foundation /* enum Optional : Reflectable, NilLiteralConvertible { case None case Some(T) init() init(_ some: T) var hasValue: Bool { get } func map(f: (T) -> U) -> U? func getMirror() -> MirrorType static func convertFromNilLiteral() -> T? } */ // Doesn't seem to work struct Regex { let pattern: String let options: NSRegularExpressionOptions! private var matcher: NSRegularExpression { return NSRegularExpression(pattern: self.pattern, options: self.options, error: nil) } init(pattern: String, options: NSRegularExpressionOptions = nil) { self.pattern = pattern self.options = options } func match(string: String, options: NSMatchingOptions = nil) -> Bool { return self.matcher.numberOfMatchesInString(string, options: options, range: NSMakeRange(0, string.utf16Count)) != 0 } } extension Regex: StringLiteralConvertible { typealias ExtendedGraphemeClusterLiteralType = StringLiteralType static func convertFromExtendedGraphemeClusterLiteral(value: ExtendedGraphemeClusterLiteralType) -> Regex { return self(pattern: value) } static func convertFromStringLiteral(value: StringLiteralType) -> Regex { return self(pattern: value) } } let string: String = "foo bar baz" let regex: Regex = "foo" regex.match(string) "foo".match(string) // ArrayLiteralConvertible and Sets struct Set { typealias Index = T private var dictionary: [T: Bool] init() { self.dictionary = [T: Bool]() } var count: Int { return self.dictionary.count } var isEmpty: Bool { return self.dictionary.isEmpty } func contains(element: T) -> Bool { return self.dictionary[element] ?? false } mutating func put(element: T) { self.dictionary[element] = true } mutating func remove(element: T) -> Bool { if self.contains(element) { self.dictionary.removeValueForKey(element) return true } else { return false } } } var basicSet: Set = Set() basicSet.put(1) basicSet.put(2) basicSet.put(3) basicSet.contains(1) basicSet.count extension Set: ArrayLiteralConvertible { static func convertFromArrayLiteral(elements: T...) -> Set { var set = Set() for element in elements { set.put(element) } return set } } let set: Set = [1, 2, 3] set.contains(1) set.count // StringLitralConvertible and URLs extension NSURL: StringLiteralConvertible { public class func convertFromExtendedGraphemeClusterLiteral(value: String) -> Self { return self(string: value) } public class func convertFromStringLiteral(value: String) -> Self { return self(string: value) } } "http://nshipster.com/".host ================================================ FILE: Swift-Playgrounds/Blogs/NSHipster/2014-08-18-SwiftLiteralConvertibles.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-23-AccessControl.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-23-AccessControl.playground/section-1.swift ================================================ // Playground - noun: a place where people can play import Cocoa import Foundation public class ListItem { // Public properties. public var text: String public var isComplete: Bool // Readable throughout the module, but only writable from within this file. private(set) var UUID: NSUUID public init(text: String, completed: Bool, UUID: NSUUID) { self.text = text self.isComplete = completed self.UUID = UUID } // Usable within the framework target, but not by other targets. func refreshIdentity() { self.UUID = NSUUID() } public func isEqual(object: AnyObject?) -> Bool { if let item = object as? ListItem { return self.UUID == item.UUID } return false } } let item1 = ListItem(text: "Item 1", completed: false, UUID: NSUUID()) ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-23-AccessControl.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-28-InteractingWithCPointers.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-28-InteractingWithCPointers.playground/section-1.swift ================================================ // Playground - noun: a place where people can play import Cocoa import CoreGraphics import XCPlayground import Accelerate var color = NSColor.magentaColor() var r: CGFloat = 0, g: CGFloat = 0, b: CGFloat = 0, a: CGFloat = 0 color.getRed(&r, green: &g, blue: &b, alpha: &a) var maybeError: NSError? if let contents = NSFileManager.defaultManager().contentsOfDirectoryAtPath("/usr/bin", error: &maybeError) { println("\(contents)") } else if let error = maybeError { println("\(error)") } let x: [Float] = [1, 2, 3, 4] let y: [Float] = [0.5, 0.25, 0.125, 0.0625] var result:[Float] = [0, 0, 0, 0] vDSP_vadd(x, 1, y, 1, &result, 1, 4) result puts("Hello fromlibc") let fd = open("/tmp/scratch.txt", O_WRONLY|O_CREAT, 0o666) if fd < 0 { perror("could not open /tmp/scratch.txt") } else { let text = "Hello World" write(fd, text, strlen(text)) close(fd) } ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-07-28-InteractingWithCPointers.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-05-Boolean.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-05-Boolean.playground/section-1.swift ================================================ // Playground - noun: a place where people can play import Cocoa enum MyBool { case myTrue, myFalse } var a: MyBool = MyBool.myTrue extension MyBool { init() { self = .myFalse } } var b: MyBool = MyBool() extension MyBool : BooleanLiteralConvertible { static func convertFromBooleanLiteral(value: Bool) -> MyBool { return value ? myTrue : myFalse } } var c: MyBool = true extension MyBool : BooleanType { var boolValue: Bool { get { switch self { case .myTrue: return true case .myFalse: return false } } } } if a { println("a is true") } extension MyBool { //MyBool can be constructed from BooleanType init(_ v : BooleanType) { if v.boolValue { self = .myTrue } else { self = .myFalse } } } var basicBool:Bool = false a = MyBool(basicBool) if a { println("a is true") } else { println("a is false") } /* // Simple enums that have no associated data (like MyBool) are automatically made Equatable by the compiler, so no additional code is required. extension MyBool : Equatable { } func ==(lhs: MyBool, rhs: MyBool) -> Bool { switch (lhs, rhs) { case (.myTrue, .myTrue), (.myFalse, .myFalse): return true default: return false } } */ if a == a { println("a == a") } if a != a { } else { println("!(a != a)") } // Binary operations func &(lhs:MyBool, rhs: MyBool) -> MyBool { if lhs { return rhs } return false } func |(lhs: MyBool, rhs: MyBool) -> MyBool { if lhs { return true } return rhs } func ^(lhs: MyBool, rhs: MyBool) -> MyBool { return MyBool(lhs != rhs) } a & b b | c c ^ a prefix func !(a: MyBool) -> MyBool { return a ^ true } // Compound assignment (with bitwise and) func &=(inout lhs: MyBool, rhs: MyBool) { lhs = lhs & rhs } !a a &= b ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-05-Boolean.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-15-ValueAndReferenceTypes.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-15-ValueAndReferenceTypes.playground/section-1.swift ================================================ // Value and Reference Types import Foundation // Value type example struct S { var data: Int = -1 } var a = S() var b = a // a is copied to b a.data = 42 // Changes a, not b println("\(a.data), \(b.data)") // Reference type example class C { var data: Int = -1 } var x = C() var y = x // x is copied to y x.data = 42 // changes the instance referred to by x (and y) println("\(x.data), \(y.data)") // Use a value type when: // - Comparing instance data with == makes sense // - You want copies to have independent state // - The data will be used in code across multiple threads // Use a reference type when: // - Comparing instance identity with === makes sense // - You want to create shared, mutable state ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-15-ValueAndReferenceTypes.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-27-OptionalCaseStudy-valuesForKeys.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-27-OptionalCaseStudy-valuesForKeys.playground/section-1.swift ================================================ // Optional Case Study: valuesForKeys import Foundation /* extension Dictionary { func valuesForKeys(keys: [K], notFoundMarkery: V) -> [V] { // to be implemented } } */ /* Beta 6 seems to report that .reserve doesn't exist? extension Dictionary { func valuesForKeys(keys: [Key]) -> [Value?] { var result = [Value?]() result.reserve(keys.count) for key in keys { result.append(self[key]) } return result } } */ extension Dictionary { func valuesForKeys(keys: [Key]) -> [Value?] { return keys.map { self[$0] } } } let dict = ["A": "Amir", "B": "Bertha", "C": "Ching"] dict.valuesForKeys(["A", "C"]) dict.valuesForKeys(["B", "D"]) // Nested Optionals dict.valuesForKeys(["A", "C"]).last dict.valuesForKeys(["B", "D"]).last dict.valuesForKeys([]).last // Providing a Default extension Dictionary { func valuesForKeys(keys: [Key], notFoundMarker: Value) -> [Value] { return self.valuesForKeys(keys).map { $0 ?? notFoundMarker } } } dict.valuesForKeys(["B", "D"], notFoundMarker: "Anonymous") ================================================ FILE: Swift-Playgrounds/Blogs/Swift Blog/2014-08-27-OptionalCaseStudy-valuesForKeys.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable ${EXECUTABLE_NAME} CFBundleIconFile CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName ${PRODUCT_NAME} CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSMinimumSystemVersion ${MACOSX_DEPLOYMENT_TARGET} NSHumanReadableCopyright Copyright © 2014 Electronic Innovations. All rights reserved. NSMainNibFile MainMenu NSPrincipalClass NSApplication ================================================ FILE: Swift-Playgrounds/Others/2014-08-11-SwiftOperators.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Others/2014-08-11-SwiftOperators.playground/section-1.swift ================================================ // Swift Operators - http://nshipster.com/swift-operators/ import Cocoa // Overloading func * (left: String, right: Int) -> String { if right <= 0 { return "" } var result = left for _ in 1.. [Double] { var sum = [Double](count: left.count, repeatedValue: 0.0) for (i, _) in enumerate(left) { sum[i] = left[i] + right[i] } return sum } println("\([1, 2] + [3, 4])") func +(left: [Int], right: [Int]) -> [Int] { var sum = [Int](count: left.count, repeatedValue: 0) for (i, _) in enumerate(left) { sum[i] = left[i] + right[i] } return sum } println("\([1, 2] + [3, 4])") // I'm specifically concerned about the semantics of array operators, as demonstrated in the previous example. My 2 cents: arrays should forego the + and - operators in lieu of <<: func << (inout left: [T], right: [T]) -> [T] { //left.extend(right) return left } func << (inout left: [T], right: T) -> [T] { //left.append(right) return left } //[1,2,3,4]<<[5,6] //[1,2,3,4]<<5 // Custom Operators infix operator ** { associativity left precedence 160 } func ** (left: Double, right: Double) -> Double { return pow(left, right) } 2 ** 3 // 8 // When creating custom operators, make sure to also create the corresponding assignment operator, if appropriate: infix operator **= { associativity right precedence 90 } func **= (inout left: Double, right: Double) { left = left ** right } // Custom Operators with Protocol and Method // First, a RegularExpressionMatchable protocol is declared, with a single method for matching regular expressions. protocol RegularExpressionMatchable { func match(pattern: String, options: NSRegularExpressionOptions) -> Bool } // Next, an extension adding conformance to this protocol to String is declared, with a provided implementation of match, using NSRegularExpression. extension String: RegularExpressionMatchable { func match(pattern: String, options: NSRegularExpressionOptions = nil) -> Bool { let regex = NSRegularExpression(pattern: pattern, options: nil, error: nil) return regex.numberOfMatchesInString(self, options: nil, range: NSMakeRange(0, self.utf16Count)) != 0 } } // Finally, the =~ operator is declared and implemented on a generic type conforming to RegularExpressionMatchable. infix operator =~ { associativity left precedence 130 } func =~ (left: T, right: String) -> Bool { return left.match(right, options: nil) } // By doing this, a user has the option to use the match function instead of the operator. It also has the added benefit of greater flexibility in what options are passed into the method. // Use of Mathematical Symbols prefix operator √ {} prefix func √ (number: Double) -> Double { return sqrt(number) } √16 √2 infix operator ± { associativity left precedence 140 } func ± (left: Double, right: Double) -> (Double, Double) { return (left + right, left - right) } prefix operator ± {} prefix func ± (value: Double) -> (Double, Double) { return 0 ± value } 2 ± 3 ±4 // Guidelines for Swift Operators // Don't create an operator unless its meaning is obvious and undisputed. Seek out any potential conflicts to ensure semantic consistency. // Custom operators should only be provided as a convenience. Complex functionality should always be implemented in a function, preferably one specified as a generic using a custom protocol. // Pay attention to the precedence and associativity of custom operators. Find the closest existing class of operators and use the appropriate precedence value. // If it makes sense, be sure to implement assignment shorthand for a custom operator (e.g. += for +). ================================================ FILE: Swift-Playgrounds/Others/2014-08-11-SwiftOperators.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday-Alternative-1.playground/Contents.swift ================================================ // When is Cheryl's Birthday // adapted from Peter Norvig's code in http://nbviewer.ipython.org/url/norvig.com/ipython/Cheryl.ipynb import Cocoa // 1. Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is. Cheryl gave them a list of 10 possible dates: // May 15 May 16 May 19 // June 17 June 18 // July 14 July 16 // August 14 August 15 August 17 // 2. Cheryl then tells Albert and Bernard seperately the month and day of the birthday respectively. // 3. Albert : I don't know when Cheryl's birthday is, but I know that Bernard does not know too. // 4. Bernard : At first I don't know when Cheryl's birthday is, but I know now. // 5. Albert : Then I also know when Cheryls birthday is. // So when is Cheryl's Birthday? let dates = ["May 15", "May 16", "May 19", "June 17", "June 18", "July 14", "July 16", "August 14", "August 15", "August 17"] func Month(date: String) -> String { return date.componentsSeparatedByString(" ")[0] } Month("May 15") func Day(date: String) -> String { return date.componentsSeparatedByString(" ")[1] } Day("May 15") func tell(part: String, possibleDates: [String]) -> [String] { return possibleDates.filter(){ $0.rangeOfString(part) != nil } } tell("May", possibleDates: dates) tell("15", possibleDates: dates) tell("18", possibleDates: dates) func know(possibleDates: [String]) -> Bool { return possibleDates.count == 1 } know(tell("15", possibleDates: dates)) // Overall Strategy // When Cheryl tells Albert "May" then he knows there are three possibilities, but we (the puzzle solvers) don't, because we don't know what Cheryl said. So what can we do? We will consider all of the possible dates, one at a time. For example, first consider "May 15". Cheryl tells Albert "May" and Bernard "15", giving them the lists of possible birthdates shown above. We can then check whether statements 3 through 5 are true in this scenario. If they are, then "May 15" is a solution to the puzzle. Repeat the process for each of the possible dates. If all goes well, there should be exactly one solution. func not(value: Bool) -> Bool { return !value } // Bernard: I don't know when Cheryl's birthday is. // Albert: I don't know when Cheryl's birthday is, but I know that Bernard doesn't know too [because he just said so]. // Bernard: At first I didn't know when Cheryl's birthday is, but I know now. // Albert: Then I also know when Cheryl's birthday is. // Bernard: I don't know when Cheryl's birthday is. func statement2(date: String) -> Bool { let bernardPossibleDates = tell(Day(date), possibleDates: dates) return not(know(bernardPossibleDates)) } let statementTwo = dates.filter(statement2) /// Albert: I don't know when Cheryl's birthday is, but I know that Bernard doesn't know too [because he just said so]. func statement3(date: String) -> Bool { let albertPossibleDates = tell(Month(date), possibleDates: dates) return not(know(albertPossibleDates)) && not(know(albertPossibleDates.filter(statement2)))} let statementThree = dates.filter(statement3) // Bernard: At first I didn't know when Cheryl's birthday is, but I know now. func statement4(date: String) -> Bool { let atFirst = tell(Day(date), possibleDates: dates) //println("\(not(know(atFirst))),\(know(filter(atFirst, statement3)))") return not(know(atFirst)) && know(atFirst.filter(statement3)) } let statementFour = dates.filter(statement4) // The dates which satisfy both statement 3 and 4 are //let statementThreeAndFour = filter(statementThree, statement4) // Albert: Then I also know when Cheryl's birthday is func statement5(date: String) -> Bool { let months = tell(Month(date), possibleDates: dates) return know(months.filter(statement4)) } let statementFive = dates.filter(statement5) func statements3to5(date: String) -> Bool { return statement2(date) && statement3(date) && statement4(date) && statement5(date) } func cherylsBirthday(possibleDates: [String]) -> [String] ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday-Alternative-1.playground/Sources/SupportCode.swift ================================================ // // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to Cheryls-Birthday-Alternative-1.playground. // ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday-Alternative-1.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday.playground/Contents.swift ================================================ // When is Cheryl's Birthday // adapted from Peter Norvig's code in http://nbviewer.ipython.org/url/norvig.com/ipython/Cheryl.ipynb import Cocoa // 1. Albert and Bernard just became friends with Cheryl, and they want to know when her birthday is. Cheryl gave them a list of 10 possible dates: // May 15 May 16 May 19 // June 17 June 18 // July 14 July 16 // August 14 August 15 August 17 // 2. Cheryl then tells Albert and Bernard seperately the month and day of the birthday respectively. // 3. Albert : I don't know when Cheryl's birthday is, but I know that Bernard does not know too. // 4. Bernard : At first I don't know when Cheryl's birthday is, but I know now. // 5. Albert : Then I also know when Cheryls birthday is. // So when is Cheryl's Birthday? let dates = ["May 15", "May 16", "May 19", "June 17", "June 18", "July 14", "July 16", "August 14", "August 15", "August 17"] func Month(date: String) -> String { return date.componentsSeparatedByString(" ")[0] } Month("May 15") func Day(date: String) -> String { return date.componentsSeparatedByString(" ")[1] } Day("May 15") func tell(part: String, possibleDates: [String]) -> [String] { return possibleDates.filter(){ $0.rangeOfString(part) != nil } } tell("May", possibleDates: dates) tell("15", possibleDates: dates) func know(possibleDates: [String]) -> Bool { return possibleDates.count == 1 } know(tell("15", possibleDates: dates)) // Overall Strategy // When Cheryl tells Albert "May" then he knows there are three possibilities, but we (the puzzle solvers) don't, because we don't know what Cheryl said. So what can we do? We will consider all of the possible dates, one at a time. For example, first consider "May 15". Cheryl tells Albert "May" and Bernard "15", giving them the lists of possible birthdates shown above. We can then check whether statements 3 through 5 are true in this scenario. If they are, then "May 15" is a solution to the puzzle. Repeat the process for each of the possible dates. If all goes well, there should be exactly one solution. func not(value: Bool) -> Bool { return !value } // Albert: After Cheryl told me the month of her birthdate, I didn't know her birthday. I don't know which day Cheryl told Bernard, but I know that for all of the possible dates, if Bernard is told that day, he wouldn't know the birthdate. func statement3(date: String) -> Bool { let albertPossibleDates = tell(Month(date), possibleDates: dates) var result = not(know(albertPossibleDates)) // Confirm that Albert doesn't know the date for d in albertPossibleDates { result = result && not(know(tell(Day(d), dates))) } return result } statement3("May 15") let statementThree = dates.filter(statement3) print("Dates satisfied by Statement 3: \(statementThree)") // Bernard: At first Cheryl told me the day, and I didn't know. Then I considered just the dates for which Albert's statement3 is true, and now I know. func statement4(date: String) -> Bool { let atFirst = tell(Day(date), possibleDates: dates) return not(know(atFirst)) && know(atFirst.filter(statement3)) } // The dates which satisfy both statement 3 and 4 are let statementThreeAndFour = statementThree.filter(statement4) print("Dates satisfied by Statement 3 & 4: \(statementThreeAndFour)") // Albert: Then I also know when Cheryl's birthday is func statement5(date: String) -> Bool { let months = tell(Month(date), possibleDates: dates) return know(months.filter(statement4)) } statement5("May 15") let statementFive = dates.filter(statement5) print("Dates satisfied by Statement 5: \(statementFive)") func statements3to5(date: String) -> Bool { return statement3(date) && statement4(date) && statement5(date) } func cherylsBirthday(possibleDates: [String]) -> [String] { return possibleDates.filter ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday.playground/Sources/SupportCode.swift ================================================ // // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to Cheryls-Birthday.playground. // ================================================ FILE: Swift-Playgrounds/Others/Cheryls-Birthday.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Others/WritingSwiftClassesWithObjectiveCBehaviour.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Others/WritingSwiftClassesWithObjectiveCBehaviour.playground/section-1.swift ================================================ // Writing Swift Classes with Objective-C Behaviour // You can // - subclass Objective-C classes, // - adopt Objective-C protocols, // - take advantage of other Objective-C functionality // when writing a Swift class. // Inheriting from Objecive-C Classes import UIKit class MySwiftViewController: UIViewController { } // Adopting Protocols /* class AnotherSwiftViewController: UIViewController, UITableViewDelegate, UITableViewDataSource { } */ // Interacting with Interface Builder // Working with Oulets and Actions // // When you declare an outlet in Swift, // - the compiler automatically converts the type to a weak implicitly unwrapped optional // - assigns it an initial value of nil // The compiler replaces @IBOutlet var name: Type with @IBOutlet weak var name: Type! = nil. // The compiler converts the type to an implicitly unwrapped optional so that you aren’t required to assign a value in an initializer. It is implicitly unwrapped because after your class is initialized from a storyboard or xib file, you can assume that the outlet has been connected. Outlets are weak by default because the outlets you create usually have weak relationships. class YetAnotherSwiftViewController: UIViewController { @IBOutlet var button: UIButton! //@IBOutlet var textFields: [UITextField] @IBAction func buttonTapped(_: AnyObject) { print("button tapped!") } } // Live Rendering // @IBDesignable, allows for live rendering of a custom view in IB // When you create a custom view that inherits from UIView or NSView, you can add the @IBDesignable attribute just before the class declaration. After you add the custom view to Interface Builder (by setting the custom class of the view in the inspector pane), Interface Builder renders your view in the canvas. // @IBInspectable, allows you to change property values of your custom classes from IB // You can also add the @IBInspectable attribute to properties with types compatible with user defined runtime attributes. After you add your custom view to Interface Builder, you can edit these properties in the inspector. @IBDesignable class DesignableCustomView: UIView { @IBInspectable var textColor: UIColor = UIColor(hue: 0.0, saturation: 0.9, brightness: 0.8, alpha: 1.0) @IBInspectable var iconHeight: CGFloat = 0.0 } // Specifying Property Attributes // Swift properties are strong by default. Use the weak keyword if required. Weak properties must be optional class types. // There are no readwrite and readonly attributes in swift. Use let for read only and var for read/write properties. // In Swift, the Objective-C copy property attribute translates to @NSCopying. // Implementing Core Data Managed Object Subclasses // “Add the @NSManaged attribute before each property definition in your managed object subclass that corresponds to an attribute or relationship in your Core Data model. Like the @dynamic attribute in Objective-C, the @NSManaged attribute informs the Swift compiler that the storage and implementation of a property will be provided at runtime. var textColor: UIColor = UIColor(hue: 0.0, saturation: 0.9, brightness: 0.8, alpha: 1.0) var textColorArray: [UIColor] = [] for i in 0..<10 { let sat = 0.1 * Float(i) var textColor: UIColor = UIColor(hue: CGFloat(sat), saturation: 0.7, brightness: 0.5, alpha: 0.9) textColorArray.append(textColor) } textColorArray ================================================ FILE: Swift-Playgrounds/Others/WritingSwiftClassesWithObjectiveCBehaviour.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/GameDevUniversity.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/GameDevUniversity.playground/section-1.swift ================================================ // Example from http://gamedevuniversity.com/swift-playground-spritekit/ // Import SpriteKit API and XCPlayground import SpriteKit import XCPlayground // Extend the SKScene to create a new Scene class GameScene:SKScene { required init(coder: NSCoder!) { super.init(coder: coder) } override init(size: CGSize) { super.init(size: size) } override func didMoveToView(view: SKView!) { // Create an Array of SKSprite var monsters = [SKSpriteNode]() // Load SKSprite to the array // Append is similar to Array push() // Note that resources in Playground are imported using their full path // Creative Commons – Attribution (CC BY 3.0) Monster designed by Ana Lourenço from the Noun Project // http://thenounproject.com/term/monster/56811/ monsters.append(SKSpriteNode(imageNamed: "/Users/danielpi/repos/Swift-Playgrounds/Swift-Playgrounds/SpriteKit/icon_56811.png")) monsters.append(SKSpriteNode(imageNamed: "/Users/danielpi/repos/Swift-Playgrounds/Swift-Playgrounds/SpriteKit/icon_56811.png")) monsters.append(SKSpriteNode(imageNamed: "/Users/danielpi/repos/Swift-Playgrounds/Swift-Playgrounds/SpriteKit/icon_56811.png")) // Loop through SKSprite array for var i=0; i<3; i++ { var monster = monsters[i] // Position the Sprite randomly var xPos = CGFloat(UInt(arc4random()) % (500 - UInt(monster.size.width)) + UInt(monster.size.width) / 2) var yPos = CGFloat(UInt(arc4random()) % (500 - UInt(monster.size.height)) + UInt(monster.size.height) / 2) monster.position = CGPoint(x: xPos, y: yPos) // Add Sprite to Scene self.addChild(monster) } } override func update(currentTime: NSTimeInterval) { } } // Create a new instance of GameScene (created above) let scene = GameScene(size: CGSize(width: 500, height: 500)) // Create a view let view = SKView(frame: NSRect(x: 0, y: 0, width: 500, height: 500)) // Present the Scene using our view view.presentScene(scene) // Use this method to render the final scene XCPShowView("result", view) ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/GameDevUniversity.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/SpriteKitTestbed.playground/Contents.swift ================================================ import Cocoa import SpriteKit import XCPlayground // Credit to http://ericasadun.com/2015/04/22/swift-simple-spritekit-experimentation/ // Build scene and view let sceneSize = CGSizeMake(400.0, 300.0) let view = SKView(frame: CGRect(origin: CGPointZero, size: sceneSize)) var scene = SKScene(size: sceneSize) scene.backgroundColor = SKColor.lightGrayColor() XCPShowView("Scene", view: view) view.presentScene(scene) var shape1 = SKShapeNode(circleOfRadius: 20.0) shape1.fillColor = SKColor.redColor() scene.addChild(shape1) shape1.position = CGPointMake(200.0, 150.0) var action = SKAction.repeatActionForever(SKAction.moveBy(CGVectorMake(0.02, 0.1), duration: 0.01)) shape1.runAction(ac ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/SpriteKitTestbed.playground/Sources/SupportCode.swift ================================================ // // This file (and all other Swift source files in the Sources directory of this playground) will be precompiled into a framework which is automatically made available to SpriteKitTestbed.playground. // ================================================ FILE: Swift-Playgrounds/Specific Technologies/SpriteKit/SpriteKitTestbed.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Array.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Array.playground/section-1.swift ================================================ // Swift Standard Library - Types - Array // An Array is a generic type that manages an ordered collection of items, all of which must be of the same underlying type. // Creating and Array var emptyArray = Array() var equivilentEmptyArray = [Int]() let numericArray = Array(count: 3, repeatedValue: 42) let stringArray = Array(count: 2, repeatedValue: "Hello") // Accessing Array Elements var subscriptableArray = ["zero", "one", "two", "three"] let zero = subscriptableArray[0] let three = subscriptableArray[3] subscriptableArray[0] = "nothing" subscriptableArray[3] = "three items" subscriptableArray // It is not possible to insert additional items into the array using subscripting: // subscriptableArray[4] = "new item" // Fatal erro: Array Index out of range // Instead use append() or += // You also can't modify the contents of an array that was initialised using let let constantArray = ["zero", "one", "two", "three"] //constantArray[0] = "nothing" subscriptableArray = ["zero", "one", "two", "three"] let subRange = subscriptableArray[1...3] subscriptableArray[1...2] = ["oneone", "twotwo"] subscriptableArray subscriptableArray[1...2] = [] subscriptableArray // It is not possible to insert additional items into the array using subscripting //subscriptableArray[4...5] = ["four", "five"] // Adding and Removing Elements var array = [0, 1] array.append(2) array array.append(3) array // You can only append to an array that has been initialised with the var keyword. //constantArray.append("another") array = [1, 2, 3] array.insert(0, atIndex: 0) array // The index must be less than or equal to the number of items in the collection //array.insert(6, atIndex: 6) // You can't insert into an array that was initialised with let let removed = array.removeAtIndex(0) array // The index must be valid // You can't remove from an array that was created with let let lastRemoved = array.removeLast() array // There must be at least one element in the array // You can't removeLast() from a constant array array = [0, 1, 2, 3] array.removeAll() let count = array.count array // Unless you specify otherwise, the underlying backing storage will be cleared array = [0, 1, 2, 3] array.removeAll(keepCapacity: true) array array.reserveCapacity(10) // Ensures that the underlying storage can hold the given total number of elements // Querying an array var arrayToCount = ["zero", "one", "two"] let firstCount = arrayToCount.count arrayToCount += ["three"] let secondCount = arrayToCount.count let firstIsEmpty = arrayToCount.isEmpty arrayToCount.removeAll() let secondIsEmpty = arrayToCount.isEmpty var capacity = arrayToCount.capacity arrayToCount.reserveCapacity(1000) capacity = arrayToCount.capacity // Algorithms // Sort // The closure that you supply for isOrderedBefore should return a Boolean value to indicate whether one element should be before (true) or after (false) another element: var arrayToSort = [3, 2, 5, 1, 4] arrayToSort.sort { $0 < $1 } arrayToSort arrayToSort.sort { $1 < $0 } arrayToSort // You can only sort an array inplace if it was declared with var arrayToSort = [3, 2, 5, 1, 4] let sortedArray = arrayToSort.sorted { $0 < $1 } sortedArray let descendingArray = arrayToSort.sorted { $1 < $0 } descendingArray sortedArray let reversedArray = sortedArray.reverse() reversedArray let filteredArray = sortedArray.filter { $0 % 2 == 0 } filteredArray let multipliedArray = sortedArray.map { $0 * 2 } multipliedArray let describedArray = sortedArray.map { "Number: \($0)" } describedArray let addResult = sortedArray.reduce(0) { $0 + $1 } addResult let multipliedResult = sortedArray.reduce(0) { $0 * $1 } multipliedResult // Operators var operatorArray = [0, 1, 2] operatorArray += [3] operatorArray += [4, 5, 6] // The type of elements must match // You can only add new elements to an array that has been declared with var ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Array.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Dictionary.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Dictionary.playground/section-1.swift ================================================ // Swift Standard Library - Types - Dictionary var emptyDictionary = Dictionary() var equivilentEmptyDictionary = [String: Int]() var anotherEmptyDictionary = Dictionary(minimumCapacity: 10) var literalDictionary = ["a":1] // Accessing and Changing Dictionary Elements var dictionary = ["one": 1, "two": 2, "three": 3] let value = dictionary["two"] if let unwrappedValue = dictionary["three"] { print("The integer value for \"three\" was: \(unwrappedValue)") unwrappedValue } dictionary["three"] = 33 dictionary // You can add to a dictionary using subscripting dictionary["four"] = 4 dictionary // you can remove a value for a key by setting it to nil dictionary["three"] = nil dictionary // You can't change, add or remove elements to a constant dictionary dictionary = ["one": 1, "two": 2, "three": 3] let previousValue = dictionary.updateValue(22, forKey: "two") dictionary if let unwrappedPreviousValue = dictionary.updateValue(33, forKey: "three") { print("Replaced the previous value: \(unwrappedPreviousValue)") } else { print("Added a new value") } dictionary = ["one": 1, "two": 2, "three": 3] let prevValue = dictionary.removeValue(forKey: "two") if let unwrappedPreviousValue = dictionary.removeValue(forKey: "three") { print("Removed the old value: \(unwrappedPreviousValue)") } else { print("Didn't find a value for the given key to delete") } dictionary.removeAll() dictionary // Querying a Dictionary dictionary = ["one": 1, "two": 2, "three": 3] let elementCount = dictionary.count for key in dictionary.keys { print("Key: \(key)") } let keysArray = Array(dictionary.keys) for value in dictionary.values { print("Value: \(value)") } let valuesArray = Array(dictionary.values) // Operators let dictionary1 = ["one": 1, "two": 2] var dictionary2 = ["one": 1] dictionary2["two"] = 2 let result = dictionary1 == dictionary2 dictionary2 = ["one": 1] let secondResult = dictionary1 != dictionary2 ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/FreeFunctions.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/FreeFunctions.playground/section-1.swift ================================================ // Swift Standard Library - Free Functions print("Hello, world!\n") println("Hello, world!") var array = [5, 1, 6, 4, 2, 3] sort(&array) array // You can't sort a constant array because sort mutates the array it operates on. array = [5, 1, 6, 4, 2, 3] var result = sorted(array) array = [5, 1, 6, 4, 2, 3] sort(&array) { $0 > $1 } array ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/FreeFunctions.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/NumericTypes.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/NumericTypes.playground/section-1.swift ================================================ // Swift Standard Library - Types - Numeric Types // Boolean var aBool: Bool aBool = true aBool = false !aBool aBool.description aBool.getMirror() aBool.hashValue // Int // The primary integer type in Swift is Int, which is word-sized. This means that it holds 32 bits on 32-bit platforms, and 64 bits on 64-bit platforms. // For the majority of use cases, you should use the base Int type. var anInt = Int() anInt.advancedBy(3) anInt.advancedBy(5) // I don't understand this one anInt anInt = -10 anInt.distanceTo(20) anInt.encode() anInt.getMirror() anInt.predecessor() anInt.successor() // Int is 64 bit on my Mac OS X system Int.min Int.max UInt.min let maxUInt = UInt.max println("Max UInt = \(maxUInt)") Int8.min Int8.max Int16.min Int16.max Int32.min Int32.max Int64.min Int64.max UInt8.min UInt8.max UInt16.min UInt16.max UInt32.min UInt32.max UInt64.min UInt64.max // Floating Point // The primary floating-point type in Swift is Double, which uses 64 bits. If you do not require 64-bit precision, Swift also includes a 32-bit Float type. var aDouble = Double() aDouble.advancedBy(5) aDouble.description aDouble.isFinite aDouble.isInfinite aDouble.isNaN aDouble.isNormal aDouble.isSignaling aDouble.isSignMinus aDouble.isSubnormal aDouble.isZero aDouble = 1.0 / 0.0 aDouble.isInfinite aDouble.isNaN aDouble = Double.NaN aDouble.isNaN aDouble = Double.abs(-7.3) ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/NumericTypes.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Protocols.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Protocols.playground/section-1.swift ================================================ // Swift Standard Library - Protocols // Equatable // The Equatable protocol makes it possible to determine whether two values of the same type are considered to be equal. struct MyEquatableStruct: Equatable { var name = "Untitled" } func == (lhs: MyEquatableStruct, rhs: MyEquatableStruct) -> Bool { return lhs.name == rhs.name } let value1 = MyEquatableStruct() var value2 = MyEquatableStruct() let firstCheck = value1 == value2 value2.name = "A New Name" let secondCheck = value1 == value2 // Comparable // The Comparable protocol makes it possible to compare two values of the same type // There is one required operator overload defined in the protocol (<) as well as one defined in the inherited Equatable protocol (==). You get >, <= and >= for free. struct MyComparableStruct: Comparable { var name = "Untitled" } func == (lhs: MyComparableStruct, rhs: MyComparableStruct) -> Bool { return lhs.name == rhs.name } func < (lhs: MyComparableStruct, rhs: MyComparableStruct) -> Bool { return lhs.name < rhs.name } let value3 = MyComparableStruct() var value4 = MyComparableStruct() let thirdCheck = value3 < value4 value4.name = "A New Name" let fourthCheck = value4 < value3 let fifthCheck = value4 > value3 let sixthCheck = value4 <= value3 let seventhCheck = value4 >= value3 // Printable // The Printable protocol allows you to customize the textual representation of any type ready for printing (for example, to Standard Out). struct MyPrintableStruct: Printable { var name = "Untitled" var description: String { return "MyType: \(name)" } } let value = MyPrintableStruct() println("Created a \(value)") // Not working in Beta-3 // Sequence Protocol // https://medium.com/swift-programming/sequence-beyond-primitive-iterations-in-swift-80bc2507d8cc class TodoItem { var name:String var priority:Int init(name:String, priority:Int) { self.name = name self.priority = priority } } struct GenericGenerator: GeneratorType { var items:[T] mutating func next() -> T? { return items.isEmpty ? .None : items.removeAtIndex(0) } } class TodoItemRepository : SequenceType { var items:[TodoItem] = []; func addItem(item:TodoItem) { items += [item] } func generate() -> GenericGenerator { return GenericGenerator(items: items) } } var repo = TodoItemRepository() repo.addItem(TodoItem(name: "One", priority: 5)) repo.addItem(TodoItem(name: "Two", priority: 2)) repo.addItem(TodoItem(name: "Three", priority: 6)) repo.addItem(TodoItem(name: "Four", priority: 0)) repo.items.count for item in repo { println("\(item.name) has a priority of \(item.priority)") } repo.items.count ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Protocols.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/String.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/String.playground/section-1.swift ================================================ // Swift Standard Library - Types - String // A String represents an ordered collection of characters. // Creating a String let emptyString = String() let equivilentString = "" let repeatedString = String(count: 5, repeatedValue: Character("a")) // Querying a String var string = "Hello, world!" let firstCheck = string.isEmpty string = "" let secondCheck = string.isEmpty string = "Hello, world!" let hasPrefixFirstCheck = string.hasPrefix("Hello") let hasPrefixSecondCheck = string.hasPrefix("hello") let hasSuffixFirstCheck = string.hasSuffix("world!") let hasSuffixSecondCheck = string.hasSuffix("World!") // Changing and Converting Strings string = "42" if let number = Int(string) { print("Got the number: \(number)") } else { print("Couldn't convert to a number") } // Operators // Concatinate + let combination = "Hello " + "world" // You can use the + operator with two strings as shown in the combination example, or with a string and a character in either order: let exclamationPoint: Character = "!" var charCombo = combination charCombo.append(exclamationPoint) //var extremeCombo: String = exclamationPoint //extremeCombo.append(charCombo) // Append += string = "Hello " string += "world" string.append(exclamationPoint) string // Equality == let string1 = "Hello world!" let string2 = "Hello" + " " + "world" + "!" let equality = string1 == string2 // Less than < let stringGreater = "Number 3" let stringLesser = "Number 2" let resulNotLessThan = stringGreater < stringLesser let resultIsLessThan = stringLesser < stringGreater // What is missing from this chapter? // - How does the less than operator work? "abc" < "def" "def" < "abc" "Number 2" < "number 1" // It just looks at the ordinal valu of the first character??? // - Does the greater than symbol work? "abc" > "def" "def" > "abc" "Number 2" > "number 1" // - How do you access the rodinal values of Characters? ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/String.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Undocumented.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Undocumented.playground/section-1.swift ================================================ // http://practicalswift.com/2014/06/14/the-swift-standard-library-list-of-built-in-functions/ import Cocoa abs(-1) abs(42) var languages = ["Swift", "Objective-C"] contains(languages, "Swift") contains(languages, "Java") contains([29, 85, 42, 96, 75], 42) var oldLanguagees = dropFirst(languages) languages languages = ["Swift", "Objective-C"] var newLanguages = dropLast(languages) languages languages = ["Swift", "Objective-C"] dump(languages) equal(languages, ["Swift", "Objective-C"]) for i in filter(1...100, { $0 % 10 == 0 }) { println(i) } find(languages, "Swift") indices([29, 85, 42]) join(":", ["A", "B", "C"]) map(1...3, { $0 * 5 }) for i in map(1...10, { $0 * 10 }) { println(i) assert(contains([10, 20, 30, 40, 50, 60, 70, 80, 90, 100],i)) } max(1, 3, 8, 2) maxElement(1...10) maxElement(languages) minElement(1...10) minElement(languages) let reducedLanguages = reduce(languages, "", { $0 + $1 }) reducedLanguages let reducedArray = reduce([10, 20, 5], 1, { $0 * $1 }) reducedArray reverse([1,2,3]) startsWith("foobar", "foo") startsWith(10..<100, 10..<15) startsWith(languages, ["Swift"]) /* abs(...) advance(...) alignof(...) alignofValue(...) assert(...) bridgeFromObjectiveC(...) bridgeFromObjectiveCUnconditional(...) bridgeToObjectiveC(...) bridgeToObjectiveCUnconditional(...) c_malloc_size(...) c_memcpy(...) c_putchar(...) contains(...) count(...) countElements(...) countLeadingZeros(...) debugPrint(...) debugPrintln(...) distance(...) dropFirst(...) dropLast(...) dump(...) encodeBitsAsWords(...) enumerate(...) equal(...) filter(...) find(...) getBridgedObjectiveCType(...) getVaList(...) indices(...) insertionSort(...) isBridgedToObjectiveC(...) isBridgedVerbatimToObjectiveC(...) isUniquelyReferenced(...) join(...) lexicographicalCompare(...) map(...) max(...) maxElement(...) min(...) minElement(...) numericCast(...) partition(...) posix_read(...) posix_write(...) print(...) println(...) quickSort(...) reduce(...) reflect(...) reinterpretCast(...) reverse(...) roundUpToAlignment(...) sizeof(...) sizeofValue(...) sort(...) split(...) startsWith(...) strideof(...) strideofValue(...) swap(...) swift_MagicMirrorData_summaryImpl(...) swift_bufferAllocate(...) swift_keepAlive(...) toString(...) transcode(...) underestimateCount(...) unsafeReflect(...) withExtendedLifetime(...) withObjectAtPlusZero(...) withUnsafePointer(...) withUnsafePointerToObject(...) withUnsafePointers(...) withVaList(...) */ ================================================ FILE: Swift-Playgrounds/Swift Stanard Library/Undocumented.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/ASwiftTour.playground/Contents.swift ================================================ // Playground - noun: a place where people can play import Cocoa var str = "Hello, world!" // Simple Values var myVariable = 42 myVariable = 50 let myConstant = 42 let implicitInteger = 70 let implicitDouble = 70.0 let explicitDouble: Double = 70 // Experiment - Create a constant with an explicit type of Float and a value of 4. let explicitFloat: Float = 4 // Values are never implicitly converted to another type. let label = "The width is " let width = 94 let widthLabel = label + String(width) // Experiment - Try removing the conversion to String from the last line. What error do you get? // let widthLabel2 = label + width // Binary operation '+' cannot be applied to operands of type 'String and 'Int' let apples = 3 let oranges = 5 let appleSummary = "I have \(apples) apples" let fruitSummary = "I have \(apples + oranges) pieces of fruit" // Experiment - Use \() to include a floating-point calculation in a string and to include someone’s name in a greeting. let π: Float = 3.14 let name = "Peter Pie" let piePy = "\(name) likes the number \(π)" let quotation = """ I said "I have \(apples) apples." And then I said "I have \(apples + oranges) pieces of fruit." """ // Arrays and Dictionaries var shoppingList = ["catfish", "water", "tulips"] shoppingList[1] = "bottle of water" shoppingList var occupations = [ "Malcom": "Captain", "Kaylee": "Mechanic", ] occupations["Jayne"] = "Public Relations" occupations // Arrays automatically grow as you add elements shoppingList.append("Blue paint") print(shoppingList) // Initialising an empty array or dict let emptyArray: [String] = [] var emptyDictionary: [String: Float] = [:] shoppingList = [] occupations = [:] // Control Flow let individualScores = [75, 43, 103, 87, 12] var teamScore = 0 for score in individualScores { if score > 50 { teamScore += 3 } else { teamScore += 1 } } teamScore // Optionals // Normal values cannot be nil. They must have a valid value. Sometimes you may not have // a valid value. In this case you can use an optional type. They are values that can either // hold a valid value or nil. var optionalString: String? = "Hello" optionalString == nil var optionalName: String? = "John Appleseed" //optionalName = nil var greeting = "Hello!" if let name = optionalName { greeting += ", \(name)" } else { greeting } let nickName: String? = nil let fullName: String = "John Appleseed" let informalGreeting: String = "Hi \(nickName ?? fullName)" // Switches let vegetable = "red pepper" switch vegetable { case "celery": print("Add some raisins and make ants on a log.") case "cucumber", "watercress": print("That would make a good tea sandwich.") case let x where x.hasSuffix("pepper"): print("Is it a spicy \(x)?") default: print("Everything tastes good in soup.") } // if default: is removed we get the error "Switch must be exhaustive". This means that every // possible option must be included in the switch/case statement so that the result cannot be // undefined. // for-in loop (Also tuples) let interestingNumbers = [ "Prime": [2,3,5,7,11,13], "Fibonacci": [1,1,2,3,5,8], "Square": [1,4,9,16,25], ] var largest = 0 var largestKind = "" for (kind, numbers) in interestingNumbers { for number in numbers { if number > largest { largest = number largestKind = kind } } } largest largestKind // while and do-while loops var n = 2 while n < 100 { n = n * 2 } n var m = 2 repeat { m = m * 2 } while m < 100 m // Indexes in loops and the Range operators var total = 0 for i in 0..<4 { total += i } total // Functions and Closures func greet(person: String, day: String) -> String { return "Hello \(person), today is \(day)." } greet(person: "Bob", day: "Tuesday") //Experiment - Remove the day parameter. Add a parameter to include today’s lunch special in the greeting. func greet(person: String, special: String) -> String { return "Hello \(person), todays lunch special is: \(special)" } greet(person: "Bob", special:"Chicken Parmigiana") func greet(_ person: String, on day: String) -> String { return "Hello \(person), today is \(day)." } greet("John", on: "Wednesday") // Use a tuple to make a compound value - for example, to return multiple values from a function. The elements of a tuple can be referred to either by name or by number func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) { var min = scores[0] var max = scores[0] var sum = 0 for score in scores { if score > max { max = score } else if score < min { min = score } sum += score } return (min, max, sum) } let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9]) statistics.sum statistics.2 // Functions can be nested func returnFifteen() -> Int { var y = 10 func add() { y = y + 5 } add() return y } returnFifteen() // Functions are a first-class type. This means that a function can return another function as its value. func makeIncrementer() -> ((Int) -> Int) { func addOne(number: Int) -> Int { return 1 + number } return addOne } var increment = makeIncrementer() increment(7) // A function can take another function as one of its arguments. func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool { for item in list { if condition(item) { return true } } return false } func lessThanTen(number: Int) -> Bool { return number < 10 } var numbers = [20, 19, 7, 12] hasAnyMatches(list: numbers, condition: lessThanTen) // Closures // Use the keyword "in" to seperate the parameters from the body numbers.map({ (number: Int) -> Int in let result = 3 * number return result }) // Experiment - Rewrite the closure to return zero for all odd numbers. numbers.map({ (number:Int) -> Int in if number % 2 == 1 { return 0 } return number }) // Single statement closures implicitly return the value of their only statement let mappedNumbers = numbers.map({ number in 3 * number}) mappedNumbers // A closure passed as the last argument to a function can appear immediately after the parentheses let sortedNumbers = numbers.sorted { $0 > $1 } sortedNumbers // Objects and Classes class Shape { var numberOfSides = 0 func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } } var shape = Shape() shape.numberOfSides = 7 var shapeDescription = shape.simpleDescription() //Experiment - Add a constant property with let, and add another method that takes an argument. extension Shape { //let solid = true func blah(a: Int) -> Int { return a * numberOfSides } } class NamedShape { var numberOfSides: Int = 0 var name: String init(name: String) { self.name = name } func simpleDescription() -> String { return "A shape with \(numberOfSides) sides." } } // Every property needs a value assigned - either in its declaration (as with numberOfSides) or in the initialiser (as with name). Note the use of self to differentiate between the name property and the name argument. class Square: NamedShape { var sideLength: Double init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name: name) numberOfSides = 4 } func area() -> Double { return sideLength * sideLength } override func simpleDescription() -> String { return "A square with sides of length \(sideLength)." } } let test = Square(sideLength:5.2, name:"My test square") test.area() test.simpleDescription() // Experiment - Make another subclass of NamedShape called Circle that takes a radius and a name as arguments to its initializer. Implement an area() and a simpleDescription() method on the Circle class. class Circle: NamedShape { var radius: Double init(radius: Double, name: String) { self.radius = radius super.init(name: name) numberOfSides = 1 } func area() -> Double { return 3.14 * radius * radius } override func simpleDescription() -> String { return "A circle with radius \(radius)" } } let testCircle = Circle(radius:2.4, name:"my test circle") testCircle.area() testCircle.simpleDescription() class EquilateralTriangle: NamedShape { var sideLength: Double = 0.0 init(sideLength: Double, name: String) { self.sideLength = sideLength super.init(name:name) numberOfSides = 3 } var perimeter: Double { get { return 3.0 * sideLength } set (newPerimeter){ sideLength = newPerimeter / 3.0 } } override func simpleDescription() -> String { return "An equilateral tringle with sides of length \(sideLength)." } } var triangle = EquilateralTriangle(sideLength:3.1, name:"my test triangle") triangle.perimeter triangle.perimeter = 9.9 triangle.sideLength class TriangleAndSquare { var triangle:EquilateralTriangle { willSet { square.sideLength = newValue.sideLength } } var square: Square { willSet { triangle.sideLength = newValue.sideLength } } init(size: Double, name: String) { square = Square(sideLength: size, name: name) triangle = EquilateralTriangle(sideLength: size, name:name) } } var triangleAndSquare = TriangleAndSquare(size:10, name:"another test shape") triangleAndSquare.square.sideLength triangleAndSquare.triangle.sideLength triangleAndSquare.square = Square(sideLength:50, name:"larger square") triangleAndSquare.triangle.sideLength // Optionals // For methods, properties and subscripts you can write a ? afterwards and everything after the question mark will be ignored if the object is nil. var optionalSquare: Square? = Square(sideLength: 2.5, name:"optional square") var sideLength = optionalSquare?.sideLength // let sideLength2 = optionalSquare.sideLength Doesn't work because optionalSquare has a type of Square? not Square. This is what the unwrapping is refering to. optionalSquare = nil sideLength = optionalSquare?.sideLength // Enumerations and Structures enum Rank: Int { case ace = 1 case two, three, four, five, six, seven, eight, nine, ten case jack, queen, king func simpleDescription() -> String { switch self { case .ace: return "ace" case .jack: return "jack" case .queen: return "queen" case .king: return "king" default: return String(self.rawValue) } } } let ace = Rank.ace let aceRawValue = ace.rawValue ace.simpleDescription() let two = Rank.two two.simpleDescription() two.rawValue // Experiment - Write a function that compares two Rank values by comparing their raw values. func compare(rank: Rank, toRank: Rank) -> Bool { return rank.rawValue == toRank.rawValue } compare(rank: ace, toRank: two) compare(rank: ace, toRank: ace) if let convertedRank = Rank(rawValue: 3) { let _ = convertedRank.simpleDescription() } // enums don't need to be backed by a raw value if they don't make sense. You can also use Int, Double or String as the raw backing type enum Suit { case spades, hearts, diamonds, clubs func simpleDescription() -> String { switch self { case .spades: return "spades" case .hearts: return "hearts" case .diamonds: return "diamonds" case .clubs: return "clubs" } } } extension Suit { func color() -> String { switch self { case .spades, .clubs: return "black" case .hearts, .diamonds: return "red" } } } let hearts = Suit.hearts let heartsDescription = hearts.simpleDescription() // hearts.toRaw() // This is an error because Suit doesnt have a raw backing type. let heartsColor = hearts.color() // Enumerations enum ServerResponse { case Result(String, String) case Error(String) } let success = ServerResponse.Result("6:00am", "8.09pm") let failure = ServerResponse.Error("Out of cheese") switch failure { case let .Result(sunrise, sunset): let _ = "Sunrise is at \(sunrise) and sunset is at \(sunset)" case let .Error(error): let _ = "Failure... \(error)" } // Experiment - Add a third case to ServerResponse and to the switch // Structures // Structures are very similar to classes. They can both have methods and initialisers. One key difference is that structures are always copied when they are passed around in code. Classes are passed by reference. struct Card { var rank: Rank var suit: Suit func simpleDescription() -> String { return "The \(rank.simpleDescription()) of \(suit.simpleDescription())" } } // Experiment - Add a method to Card that creates a full deck of cards, with one card of each combination of rank and suit extension Card { func createFullDeck() -> [Card] { var deck: [Card] = [] func appendFullRank(suit: Suit) { for rawRank in 1...13 { let card = Card(rank:Rank(rawValue:rawRank)!, suit:suit) deck.append(card) } } for suit in [Suit.hearts, Suit.diamonds, Suit.spades, Suit.clubs] { appendFullRank(suit: suit) } return deck } } let threeOfSpades = Card(rank: .three, suit:.spades) let threeOfSpadesDescription = threeOfSpades.simpleDescription() let aFullDeck = threeOfSpades.createFullDeck() aFullDeck.map({ card in card.simpleDescription() }) // Protocols and Extensions protocol ExampleProtocol { var simpleDescription: String { get } mutating func adjust() } class SimpleClass: ExampleProtocol { var simpleDescription: String = "A very simple class." var anotherProperty: Int = 69105 func adjust() { simpleDescription += " Now 100% adjusted." } } var a = SimpleClass() a.adjust() let aDescription = a.simpleDescription struct SimpleStructure: ExampleProtocol { var simpleDescription: String = "A simple structure" mutating func adjust() { simpleDescription += " (adjusted)" } } var b = SimpleStructure() b.adjust() let bDescription = b.simpleDescription // Experiment - Write an enumeration that conforms to this protocol enum SimpleEnum: Int, ExampleProtocol { case A = 1, B, C, D, E var simpleDescription: String { get { return "A simple enum \(self.rawValue)" } } mutating func adjust() { self = SimpleEnum(rawValue:(self.rawValue + 1))! } } var c = SimpleEnum.A c.adjust() let cDescription = c.simpleDescription // Extensions extension Int: ExampleProtocol { var simpleDescription: String { return "The number \(self)" } mutating func adjust() { self += 42 } } 7.simpleDescription // The 7 above is a literal constant not a variable. Therefore you can't mutate it with adjust. var someInt = 4 someInt.adjust() someInt // Experiment - Write an extension for the Double type that adds an absoluteValue property. extension Double { var absoluteValue: Double { return self > 0 ? self : -self } } var aDouble = -7.0 aDouble.absoluteValue 4.absoluteValue (-6.0).absoluteValue let neg = -6.0 neg.absoluteValue let absNeg = (-6.0.absoluteValue) let protocolValue: ExampleProtocol = a protocolValue.simpleDescription // protocolValue.anotherProperty // Uncomment to see the error // Error Handling // You represent errors using any type that adopts the Error protocol enum PrinterError: Error { case outOfPaper case noToner case onFire } func send(job: Int, toPrinter printerName: String) throws -> String { if printerName == "Never Has Toner" { throw PrinterError.noToner } return "Job sent" } do { let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng") printerResponse } catch { error } // Experiment do { let printerResponse2 = try send(job: 1040, toPrinter: "Never Has Toner") printerResponse2 } catch { error } // You can provide multiple catch blocks to handle specific errors do { let printerResponse = try send(job: 1440, toPrinter: "Gutenberg") printerResponse } catch PrinterError.onFire { print("I'll just put this over here, with the rest of the fire") } catch let printerError as PrinterError { print("Printer error: \(printerError).") } catch { print(error) } // Experiment let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler") let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner") // Defer var fridgeIsOpen: Bool = false let fridgeContent = ["milk", "eggs", "leftovers"] func fridgeContains(_ food: String) -> Bool { fridgeIsOpen = true defer { fridgeIsOpen = false } let result = fridgeContent.contains(food) return result } fridgeContains("banana") fridgeIsOpen // Generics func makeArray(repeating item: Item, numberOfTimes: Int) -> [Item] { var result = [Item]() for _ in 0.. { case none case some(Wrapped) } var possibleInteger: OptionalValue = .none possibleInteger = .some(100) func anyCommonElements (_ lhs: T, _ rhs: U) -> Bool where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element { for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { return true } } } return false } anyCommonElements([1,2,3], [3]) anyCommonElements([1,2,3], [6]) anyCommonElements([1,2,3], [3.0]) // Experiment - Modify the anyCommonElements(_:_:) function to make a function that returns an array of the elements that any two sequences have in common. func returnAnyCommonElements (_ lhs: T, _ rhs: U) -> [T.Iterator.Element] where T.Iterator.Element: Equatable, T.Iterator.Element == U.Iterator.Element { var commonElements: [T.Iterator.Element] = [] for lhsItem in lhs { for rhsItem in rhs { if lhsItem == rhsItem { commonElements.append(lhsItem) } } } return commonElements } returnAnyCommonElements([1, 2, 3], [2, 3, 4]) //returnAnyCommon ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/ASwiftTour.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/ASwiftTour.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/01-TheBasics.playground/Contents.swift ================================================ // The Basics Chapter of “The Swift Programming Language.” iBooks. https://itun.es/au/jEUH0.l //: # The Basics //: ## Constants and Variables //: ### Declaring Constants and Variables let maximumNumberOfLoginAttempts = 10 var currentLoginAttempt = 0 var x = 0.0, y = 0.0, z = 0.0 //: ### Type Annotations var welcomeMessage: String welcomeMessage = "Hello" var red, green, blue: Double //: ### Naming Constants and Variables let π = 3.14159 let 你好 = "你好世界" let 🐶🐮 = "dogcow" var friendlyWelcome = "Hello!" friendlyWelcome = "Bonjour!" let languageName = "Swift" //languageName = "Swift++" // Compile time error //: Printing Constants and Variables print(friendlyWelcome) print(π, 你好, 🐶🐮, separator: ", ", terminator: "") print("The current value of friendlyWelcome is \(friendlyWelcome)") //: ## Comments // this is a comment /* this is also a comment, but written over multiple lines*/ /* this is the start of the first multiline comment /* this is the second, nested multiline comment */ this is the end of the first multiline comment */ //: ## Semicolons let cat = "🐱"; print(cat) //: ## Integers //: ### Integer Bounds let minValue = UInt8.min let maxValue = UInt8.max //: ## Floating-Point Numbers var w = [1, 1.2] //: ## Type Safety and Type Inference var meaningOfLife = 42 // inferred to be of type Int // meaningOfLife = 35.0 //Type Error let pi = 3.14159 let anotherPi = 3 + 0.14159 //: ## Numeric Literals let descimalInteger = 17 let binaryInteger = 0b10001 let octalInteger = 0o21 let hexadecimalInteger = 0x11 //let hexFloat = 0x1234.0x5678 1.25e2 1.25e-2 0xFp2 0x8p4 let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecialDouble = 0xC.3p0 let paddedDouble = 000123.456 let oneMillion = 1_000_000 let justOverOneMillion = 1_000_000.000_000_1 //: ## Numeric Conversion //: ### Integer Conversion //let cannotBeNegative: UInt8 = -1 //let tooBig: Int8 = Int8.max + 1 let twoThousand: UInt16 = 2_000 let one: UInt8 = 1 let twoThousandAndOne = twoThousand + UInt16(one) //: ### Integer and Floating Point Conversion let three = 3 let pointOneFourOneFiveNine = 0.14159 let pi2 = Double(three) + pointOneFourOneFiveNine let integerPi = Int(pi) // Floats are always truncated when cast to Integers let integerFourPointSeven = Int(4.75) let integerNegativeThreePointNine = Int(-3.9) // Literals can be cross type combined because they have no type until they are evaluated 3 + 0.14159 //: ## Type Aliases // Type aliases are useful when you want to refer to an existing type by a name that is contextually more appropriate, such as when working with data of a specific size from an external source: typealias AudioSample = UInt16 var macAmplitudeFound = AudioSample.min //: ## Booleans let orangesAreOrange = true let turnipsAreDelicious = false if turnipsAreDelicious { print("Mmm, tasty turnips!") } else { print("Eww, turnips are horrible.") } // Non-Bool types can't be used for flow control let i = 1 /* if i { } */ if i == 1 { } //: ## Tuples let http404Error = (404, "Not Found") let (statusCode, statusMessage) = http404Error print("The status code is \(statusCode)") print("The status message is \(statusMessage)") // use _ if you don't want to decompose one of the values of a tuple let (justTheStatusCode, _) = http404Error print("The status code is \(justTheStatusCode)") // You can access the values of the tuple using index numbers print("The status code is \(http404Error.0)") print("The status message is \(http404Error.1)") // You can name the elements of a tuple when it is defined let http200Status = (statusCode: 200, description: "OK") print("The status code is \(http200Status.statusCode)") print("The status message is \(http200Status.description)") // “Tuples are useful for temporary groups of related values. They are not suited to the creation of complex data structures. If your data structure is likely to persist beyond a temporary scope, model it as a class or structure, rather than as a tuple. For more information” //: ## Optionals let possibleNumber = "123" let convertedNumber = Int(possibleNumber) // convertedNumber is inferred to be ot type "Int?" (optional Int) // nil var serverResponseCode: Int? = 404 serverResponseCode = nil var surveyAnswer: String? // surveyAnswer is automatically set to nil // If statements and forced Unwrapping if convertedNumber != nil { print("convertedNumber contains some integer value.") } if convertedNumber != nil { print("convertedNumber has an integer value of \(convertedNumber!)") } //: ### Optional Binding if let actualNumber = Int(possibleNumber) { print("\'\(possibleNumber)\' has a value of \(actualNumber)") } else { print("\'\(possibleNumber)\' could not be converted to an Int") } if let firstNumber = Int("4"), let secondNumber = Int("42"), firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") } if let firstNumber = Int("4") { if let secondNumber = Int("42") { if firstNumber < secondNumber && secondNumber < 100 { print("\(firstNumber) < \(secondNumber) < 100") } } } //: ### Implicitly Unwrapped Optionals //: Implicitly unwrapped optionals are useful when an optional’s value is confirmed to exist immediately after the optional is first defined and can definitely be assumed to exist at every point thereafter. The primary use of implicitly unwrapped optionals in Swift is during class initialization let possibleString: String? = "An optional string." let forcedString: String = possibleString! let assumedString: String! = "An implicitly unwrapped optional string" let implicitString: String = assumedString if assumedString != nil { print(assumedString) } if let definiteString = assumedString { print(definiteString) } //: Implicitly unwrapped optionals should not be used when there is a possibility of a variable becoming nil at a later point. Always use a normal optional type if you need to check for a nil value during the lifetime of a variable. //: ## Error Handling //: In contrast to optionals, which can use the presence or absence of a value to signify success or failure of a function, error handling allows you to determine the underlying cause of failure and if necessary propagate the error to another part of your program. func canThrowError() throws { // This function may or may not throw an error. } do { try canThrowError() // no error was thrown } catch { // an error was thrown } enum SandwichError: Error { case OutOfCleanDishes case MissingIngredients([String]) } func makeASandwich() throws { throw SandwichError.MissingIngredients(["butter","ham","bread"]) } func eatASandwich() { print("yum yum yum") } func washDishes() { print("Wash the dishes") } func buyGroceries(ingredients: [String]) { ingredients.forEach{ i in print(i) } } do { try makeASandwich() eatASandwich() } catch SandwichError.OutOfCleanDishes { washDishes() } catch SandwichError.MissingIngredients(let ingredients) { buyGroceries(ingredients: ingredients) } catch { print("Why did I fail") } //: ## Assertions and Preconditions //: ### Debugging with Assertions //: Use an assertion whenever a condition has the potential to be false, but must definitely be true in order for your code to continue execution. let age = -3 //assert(age >= 0, "A person's age cannot be less than zero") // Left this out as it stops the REPL from continuing //: ### Enforcing Preconditions var index = -3 precondition(index > 0, "Index must be greater than zero.") ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/01-TheBasics.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/02-BasicOperators.playground/Contents.swift ================================================ // Basic Operators // Assignment operator let b = 10 var a = 5 a = b let (x, y) = (1, 2) /* // “Unlike the assignment operator in C and Objective-C, the assignment operator in Swift does not itself return a value. The following statement is not valid:” if x = y { } */ // Arithmetic Operators 1 + 2 5 - 3 2 * 3 10.0 / 2.5 // Swift Arithmetic operators can't overflow "hello, " + "world" let dog: Character = "🐶" let cow: Character = "🐮" //let dogcow = dog + cow // This has been removed from the book. let dogcow = "🐶" + "🐮" // Remainder Operator 9 % 4 // a = (b × some multiplier) + remainder -9 % 4 // a % b and a % -b 9 % -4 -9 % -4 // Unary Minus Operator let three = 3 let minusThree = -three let plusThree = -minusThree // Unary Plus Operator // Doesn't do anything let minusSix = -6 let alsoMinusSix = +minusSix // Compound Assignment Operators var aaa = 1 aaa += 2 // Comparison Operators 1 == 1 2 != 1 2 > 1 1 < 2 1 >= 1 2 <= 1 let name = "world" if name == "world" { print("hello, world") } else { print("I'm sorry \(name), but I don't recognize you") } // Identity operators // “Swift also provides two identity operators (=== and !==), which you use to test whether two object references both refer to the same object instance.” // Ternary Conditional Operator let contentHeight = 40 let hasHeader = true let rowHeight = contentHeight + (hasHeader ? 50 : 20) // Range Operators // The Closed Range Operator for index in 1...5 { print("\(index) times 5 is \(index * 5)") } // The Half-Closed range operator let names = ["Anna", "Alex", "Brian", "Jack"] let count = names.count for i in 0.. ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/02-BasicOperators.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/03-StringsAndCharacters.playground/Contents.swift ================================================ // Strings and Characters let someString = "Some tring literal value" let quotation = """ The White Rabbit put on his spectacles. "Where shall I begin, please your Majesty?" he asked. "Begin at the beginning," the king said gravely, "and go on till you come to the end; then stop." """ let threeDoubleQuotes = """ Escaping the first quote \""" Escaping all three quotes \"\"\" """ let singleLineString = "These are the same." let mutilineString = """ These are the same. """ """ This string starts with a line feed. It also ends with a line feed. """ func generateQuotation() -> String { let quotation = """ The White Rabbit put on his spectacles. "Where shall I begin, please your Majesty?" he asked. "Begin at the beginning," the king said gravely, "and go on till you come to the end; then stop." """ return quotation } print(quotation == generateQuotation()) // Initializing an Empty Strings var emptyString = "" var anotherEmpyString = String() if emptyString.isEmpty { print("Nothing to see here") } // String mutability var variableString = "Horse" variableString += " and carriage" let constantString = "Highlander" // constantString += " and another Highlander" // There can be only one // Working with Characters for character in "Dog!🐶".characters { print(character) } let exclamationMark: Character = "!" let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"] let catString = String(catCharacters) print(catString) catString // Concatenating Strings and Characters let string1 = "Hello" let string2 = " there" var welcome = string1 + string2 // Welcome now equals "hellow there" var instruction = "look over" instruction += string2 welcome.append(exclamationMark) // String Interpolation let multiplier = 3 let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)" // Special Characters in String LIterals let wiseWords = "\"Imagination is more important than knowledge\" - Einstein" // "Imagination is more important than knowledge" - Einstein let dollarSign = "\u{24}" // $, Unicode scalar U+0024 let blackHeart = "\u{2665}" // ♥, Unicode scalar U+2665 let sparklingHeart = "\u{1F496}" // 💖, Unicode scalar U+1F496 // Extended Grapheme Clusters let eAcute: Character = "\u{E9}" // é let combinedEAcute: Character = "\u{65}\u{301}" // e followed by ́ // eAcute is é, combinedEAcute is é let precomposed: Character = "\u{D55C}" // 한 let decomposed: Character = "\u{1112}\u{1161}\u{11AB}" // ᄒ, ᅡ, ᆫ // precomposed is 한, decomposed is 한 let enclosedEAcute: Character = "\u{E9}\u{20DD}" // enclosedEAcute is é⃝ let regionalIndicatorForUS: Character = "\u{1F1FA}\u{1F1F8}" // regionalIndicatorForUS is 🇺🇸 let regionalIndicatorForAUS: Character = "\u{1F1E6}\u{1F1FA}" // regionalIndicatorForAUS is 🇦🇺 // Counting Characters let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪" print("unusualMenagerie has \(unusualMenagerie.characters.count) characters") // prints "unusualMenagerie has 40 characters" // Note that Swift's use of extended grapheme clusters for Character values means that string concatenation and modification may not always affect a string's character count. var word = "cafe" print("the number of characters in \(word) is \(word.characters.count)") // prints "the number of characters in cafe is 4" word += "\u{301}" // Combining Acute accent, U+301 print("the number of characters in \(word) is \(word.characters.count)") // prints "the number of characters in café is 4" // Accessing and Modifying a String // String Indices // Different characters can require different amounts of memory to store, so in order to determine which Character is at a particular position, you must iterate over each Unicode scalar from the start or end of that String. For this reaason, Swift strings cannot be indexed by integer values. let greeting = "Guten Tag!" greeting[greeting.startIndex] // G greeting[greeting.index(before: greeting.endIndex)] // ! greeting[greeting.index(after: greeting.startIndex)] // u let index = greeting.index(greeting.startIndex, offsetBy: 7) greeting[index] // a // greeting[greeting.endIndex] // error // greeting.endIndex.successor() // error for index in greeting.characters.indices { print("\(greeting[index]) ", terminator: "") } // prints "G u t e n T a g !" // Inserting and Removing // To insert a character at a specified index. var welcome2 = "hello" welcome2.insert("!", at: welcome2.endIndex) // To insert another string at a specified index welcome2.insert(contentsOf:" there".characters, at: welcome2.index(before: welcome2.endIndex)) // To remove a character at a specified index welcome2.remove(at: welcome2.index(before: welcome2.endIndex)) welcome2 // To remove a substring let range = welcome2.index(welcome2.endIndex, offsetBy: -6).. ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/04-CollectionTypes.playground/Contents.swift ================================================ // Collection Types // Arrays // Creating an Empty Array var someInts = [Int]() print("someInts is of type [Int] with \(someInts.count) items.") // Creating an Array with a Default Value var threeDoubles = Array(repeating: 0.0, count: 3) // Creating an Array by Adding Two Arrays Together var anotherThreeDoubles = Array(repeating: 2.5, count: 3) var sixDoubles = threeDoubles + anotherThreeDoubles // Creating an Array with an Array Literal var shoppingList: [String] = ["Eggs","Milk"] // Accessing and Modifying an Array print("The shopping list contains \(shoppingList.count) items.") if shoppingList.isEmpty { print("The shopping list is empty.") } else { print("The shopping list is not empty") } shoppingList.append("Flour") shoppingList += ["Baking Powder"] shoppingList += ["Chocolate Spread", "Cheese", "Butter"] var firstItem = shoppingList[0] shoppingList[0] = "Six eggs" shoppingList[4...6] = ["Bananas", "Apples"] shoppingList.insert("Maple Syrup", at: 0) let mapleSyrup = shoppingList.remove(at: 0) firstItem = shoppingList[0] let apples = shoppingList.removeLast() // Iterating Over an Array for item in shoppingList { print(item) } for (index, value) in shoppingList.enumerated() { print("Item \(index + 1): \(value)") } // Sets // Hash Values for Set Types // A type must be hashable in order to be stored in a set. // Creating and Initializing an Empty Set var letters = Set() print("letters is of type Set with \(letters.count) items.") letters.insert("a") letters = [] // letters is now an empty set, but is still of type Set // Creating a Set with an Array Literal var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"] let alsoFavoriteGenres: Set = ["Rock", "Classical", "Hip hop"] // Accessing and Modifying a Set print("I have \(favoriteGenres.count) favorite music genres.") if favoriteGenres.isEmpty { print("As far as music goes, I'm not picky.") } else { print("I have particular music preferences.") } favoriteGenres.insert("Jazz") if let removedGenre = favoriteGenres.remove("Rock") { print("\(removedGenre)? I'm over it.") } else { print("I never much cared for that.") } if favoriteGenres.contains("Funk") { print("I get up on the good foot.") } else { print("It's too funky in here.") } // Iterating Over a Set for genre in favoriteGenres { print("\(genre)") } for genre in favoriteGenres.sorted() { print("\(genre)") } //for genre in favoriteGenres.sorted({ $0[$0.endIndex.predecessor()] > $1[$1.endIndex.predecessor()] }) { // print("\(genre)") //} for genre in favoriteGenres.sorted().reversed() { print("\(genre)") } // Performing Set Operations let oddDigits: Set = [1,3,5,7,9] let evenDigits: Set = [0,2,4,6,8] let singleDigitPrimeNumbers: Set = [2,3,5,7] oddDigits.union(evenDigits).sorted() oddDigits.intersection(evenDigits).sorted() oddDigits.subtracting(singleDigitPrimeNumbers).sorted() oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted() // Set Membership and Equality // Set a is a superset of set b, because a contains all elements of b // Set b is a subset of a // Set b and set c are disjoint with one another as they share no elements in common let houseAnimals: Set = ["🐶", "🐱"] let farmAnimals: Set = ["🐮", "🐔", "🐑", "🐶", "🐱"] let cityAnimals: Set = ["🐦", "🐭"] houseAnimals.isSubset(of: farmAnimals) farmAnimals.isSuperset(of: houseAnimals) farmAnimals.isDisjoint(with: cityAnimals) // Dictionaries let alongFormDict = Dictionary() let shortFormDict = [String:Int]() // Creating an Empty Dictionary var namesOfIntegers = [Int: String]() namesOfIntegers[16] = "sixteen" namesOfIntegers = [:] // Creating a Dictionary with a Dictionary Literal //var airports: Dictionary = ["TYO":"Tokyo", "DUB":"Dublin"] var airports: [String: String] = ["YYZ":"Toronto Pearson", "DUB":"Dublin"] // Accessing and Modifying a Dictionary print("The dictionary of airports contains \(airports.count) items.") if airports.isEmpty { print("The airports dictionary is empty.") } else { print("The airports dictionary is not empty.") } airports["LHR"] = "London" airports["LHR"] = "London Heathrow" if let oldValue = airports.updateValue("Dublin International", forKey: "DUB") { print("The old value for DUB was \(oldValue).") } if let airportName = airports["DUB"] { print("The name of the airport is \(airportName)") } else { print("That airport is not in the airports dictionary.") } airports["APL"] = "Apple International" airports["APL"] = nil if let removedValue = airports.removeValue(forKey: "DUB") { print("The removed airport's name is \(removedValue).") } else { print("The airports dictionary does not contain a value for DUB.") } // Iterating over a dictionary for (airportCode, airportName) in airports { print("\(airportCode): \(airportName)") } for airportCode in airports.keys { print("Airport code: \(airportCode)") } for airportName in airports.values { print("Airport name: \(airportName)") } let airportCodes = [String](airports.keys) let airportNames = [String](airports.values) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/04-CollectionTypes.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/05-ControlFlow.playground/Contents.swift ================================================ // Control Flow Chapter // For Loops // For-In for index in 1...5 { print("\(index) times 5 is \(index * 5)") } let base = 3 let power = 10 var answer = 1 for _ in 1...power { answer *= base } let names = ["Anna", "Alex", "Brian", "Jack"] for name in names { print("Hello, \(name)!") } let numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] for (animalName, legCount) in numberOfLegs { print("\(animalName)s have \(legCount) legs") } // While Loops // While let finalSquare = 25 var board = [Int](repeating: 0, count: finalSquare + 1) board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 var square = 0 var diceRoll = 0 while square < finalSquare { // roll the dice diceRoll += 1 if diceRoll == 7 { diceRoll = 1 } // move by the rolled amount square += diceRoll if square < board.count { // if we're still on the board, move up or down for a snake or a ladder square += board[square] } } print("Game over!") // Repeat-While square = 0 diceRoll = 0 repeat { // move up or down for a snake or ladder square += board[square] // roll the dice diceRoll += 1 if diceRoll == 7 { diceRoll = 1 } // move by the rolled amount square += diceRoll } while square < finalSquare print("Game over!") // Conditional Statements // If var temperatureInFarenheit = 30 if temperatureInFarenheit <= 32 { print("It's very cold. Consider wearing a scarf") } temperatureInFarenheit = 40 if temperatureInFarenheit <= 32 { print("It's very cold. Consider wearing a scarf") } else { print("It's not that cold. wear a t-shirt.") } temperatureInFarenheit = 90 if temperatureInFarenheit <= 32 { print("It's very cold. Consider wearing a scarf") } else if temperatureInFarenheit >= 86 { print("It's really warm. Don't forget to wear sunscreen.") } else { print("It's not that cold. wear a t-shirt.") } temperatureInFarenheit = 72 if temperatureInFarenheit <= 32 { print("It's very cold. Consider wearing a scarf") } else if temperatureInFarenheit >= 86 { print("It's really warm. Don't forget to wear sunscreen.") } // Switch let someCharacter: Character = "e" switch someCharacter { case "a", "e", "i", "o", "u": print("\(someCharacter) is a vowel") case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z": print("\(someCharacter) is a consonant") default: print("\(someCharacter) is not a vowel or consonant") } // No Implicit Fallthrough let anotherCharacter: Character = "a" switch anotherCharacter { //case "a": // Not valid if this line is in place as no executble line for this case statement. case "A": print("The letter A") default: print("Not the letter A") } // Interval Matching let approximateCount = 62 let countedThings = "moons orbitiy Saturn" var naturalCount: String switch approximateCount { case 0: naturalCount = "no" case 1..<5: naturalCount = "a few" case 5..<12: naturalCount = "several" case 12..<100: naturalCount = "dozens of" case 100..<1000: naturalCount = "hundreds of" default: naturalCount = "manu" } print("There are \(naturalCount) \(countedThings).") // Note: Both the closed range operator (...) and half-open range operator (..<) functions are overloaded to return either an IntervalType or Range. An interval can determine whether it contains a particular element, such as when matching a switch statement case. A range is a collecton of consecutive values, which can be iterated on in a for-in statement. // Tuples let somePoint = (1,1) switch somePoint { case (0, 0): print("(0,0) is at the origin") case (_, 0): print("\(somePoint.0),0) is on the x-axis") case (0, _): print("(0, \(somePoint.1)) is on the y-axis") case (-2...2, -2...2): print("(\(somePoint.0, somePoint.1)) is inside the box") default: print("(\(somePoint.0, somePoint.1)) is outside of the box") } // Value Bindings let anotherPoint = (2, 0) switch anotherPoint { case (let x, 0): print("on the x-axis with an x value of \(x)") case (0, let y): print("on the y-axis with a y value of \(y)") case let (x, y): print("somewhare else at (\(x), \(y))") } // Where let yetAnotherPoint = (1, -1) switch yetAnotherPoint { case let (x, y) where x == y: print("(\(x), \(y)) is on the line x == y") case let (x, y) where x == -y: print("(\(x), \(y)) is on the line x == -y") case let (x, y): print("(\(x), \(y)) is just some arbitrary point") } // Control Transfer Statements // Continue let puzzleInput = "great minds think alike" var puzzleOutput = "" for character in puzzleInput.characters { switch character { case "a", "e", "i", "o", "u", " ": continue default: puzzleOutput.append(character) } } puzzleOutput // Break let numberSymbol: Character = "三" // Simplified Chinese for the number 3” var possibleIntegerValue: Int? switch numberSymbol { case "1", "١", "一", "๑": possibleIntegerValue = 1 case "2", "٢", "二", "๒": possibleIntegerValue = 2 case "3", "٣", "三", "๓": possibleIntegerValue = 3 case "4", "٤", "四", "๔": possibleIntegerValue = 4 default: break } if let integerValue = possibleIntegerValue { print("The integer value of \(numberSymbol) is \(integerValue).") } else { print("An integer value could not be found for \(numberSymbol).") } // Fallthrough let integerToDescribe = 5 var description = "The number \(integerToDescribe) is" switch integerToDescribe { case 2, 3, 5, 7, 11, 13, 17, 19: description += " a prime number, and also" fallthrough default: description += " an integer." } print(description) // Labelled Statements board = [Int](repeating: 0, count: finalSquare + 1) board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 square = 0 diceRoll = 0 gameLoop: while square != finalSquare { diceRoll += 1 if diceRoll == 7 { diceRoll = 1} switch square + diceRoll { case finalSquare: break gameLoop case let newSquare where newSquare > finalSquare: continue gameLoop default: square += diceRoll square += board[square] } } print("Game over!") // Early Exit // Guard func greet(person: [String: String]) { guard let name = person["name"] else { return } print("Hello \(name)!") guard let location = person["location"] else { print("I hope the weather is nice near you.") return } print("I hope the weather is nice in \(location).") } greet(person: [:]) greet(person: ["name": "John"]) greet(person: ["name":"Jane", "location": "Cupertino"]) // Checking API Availability if #available(iOS 9, OSX 10.12, *) { print("Use iOS 9 APIs on iOS, and use OS X v10.10 APIs on OS X") } else { print("Fall back to earlier iOS and OSX APIs") } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/05-ControlFlow.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/05-ControlFlow.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/06-Functions.playground/Contents.swift ================================================ //: # Functions Chapter func greet(person: String) -> String { let greeting = "Hello, " + person + "!" return greeting } print(greet(person: "Anna")) print(greet(person: "Brian")) func greetAgain(person: String) -> String { return "Hello, " + person + "!" } print(greetAgain(person: "Anna")) // Function Parameters and Return Values // Functions Without Parameters func sayHelloWorld() -> String { return "hello, world" } print(sayHelloWorld()) // Multiple Input Parameters func greet(person: String, alreadyGreeted: Bool) -> String { if alreadyGreeted { return greetAgain(person: person) } else { return greet(person: person) } } print(greet(person: "Time", alreadyGreeted: true)) // Functions Without Return Values func greet2(person: String) { print("Hello, \(person)!") } greet2(person: "Dave") func printAndCount(string: String) -> Int { print(string) return string.characters.count } func printWithoutCounting(string: String) { let _ = printAndCount(string: string) } printAndCount(string: "hello, world") printWithoutCounting(string: "hello, world") // Functions with Multiple Return Values func minMax(array: [Int]) -> (min: Int, max: Int) { var currentMin = array[0] var currentMax = array[0] for value in array[1.. currentMax { currentMax = value } } return (currentMin, currentMax) } let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) print("min is \(bounds.min) and max is \(bounds.max)") // Optional Tuple Return Types func minMaxSafe(array: [Int]) -> (min: Int, max: Int)? { if array.isEmpty {return nil } var currentMin = array[0] var currentMax = array[0] for value in array[1.. currentMax { currentMax = value } } return (currentMin, currentMax) } if let bounds = minMaxSafe(array: [8, -6, 2, 109, 3, 71]) { print("min is \(bounds.min) and max is \(bounds.max)") } // Function Argument Labels and Parameter Names // External Parameter Names func someFunction(firstParameterName: Int, secondParameterName: Int) { } someFunction(firstParameterName: 1, secondParameterName: 2) // Secifying Argument Labels func greet(person: String, from hometown: String) -> String { return "Hello \(person)! Glad you could visit from \(hometown)." } greet(person: "Bill", from: "Cupertino") // Omitting Argument Labels func someFunction(_ firstParameterName: Int, secondParameterName: Int) { } someFunction(1, secondParameterName: 2) // Default Parameter Values func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) { } someFunction(parameterWithoutDefault: 3, parameterWithDefault: 6) someFunction(parameterWithoutDefault: 4) // Variadic Parameters func arithmeticMean(_ numbers: Double...) -> Double { var total: Double = 0 for number in numbers { total += number } return total / Double(numbers.count) } arithmeticMean(1, 2, 3, 4, 5) arithmeticMean(3, 8, 19) // In-Out Parameters func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // Function Types // Every function has a specific function type, made up of the parameter types and the return type of the function. func addTwoInts(_ a: Int, _ b: Int) -> Int { return a + b } func multiplyTwoInts(_ a: Int, _ b: Int) -> Int { return a * b } func printHelloWorld() { print("hello, world") } // Using Function Types // you can define a constant or variable to be of a function type and assign an appropriate function to that variable: var mathFunction: (Int, Int) -> Int = addTwoInts print("Result: \(mathFunction(2, 3))") mathFunction = multiplyTwoInts print("Result: \(mathFunction(2, 3))") let anotherMathFunction = addTwoInts // Function Types as Parameter Types func printMathResult(_ mathFunction: (Int, Int) -> Int, _ a: Int, _ b: Int) { print("Result: \(mathFunction(a, b))") } printMathResult(addTwoInts, 3, 5) // Function Types as Return Types func stepForward(_ input: Int) -> Int { return input + 1 } func stepBackward(_ input: Int) -> Int { return input - 1 } func chooseStepFunction(backward: Bool) -> (Int) -> Int { return backward ? stepBackward : stepForward } var currentValue = 3 let moveNearerToZero = chooseStepFunction(backward: currentValue > 0) print("Counting to zero:") while currentValue != 0 { print("\(currentValue)... ") currentValue = moveNearerToZero(currentValue) } print("zero!") // Nested Functions func chooseAnotherStepFunction(backward: Bool) -> (Int) -> Int { func stepForward(input: Int) -> Int { return input + 1 } func stepBackward(input: Int) -> Int { return input - 1 } return backward ? stepBackward : stepForward } currentValue = -4 let moveNearerToZeroAgain = chooseAnotherStepFunction(backward: currentValue > 0) while currentValue != 0 { print("\(currentValue)... ") currentValue = moveNearerToZeroAgain(currentValue) } print("zero!") ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/06-Functions.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/07-Closures.playground/Contents.swift ================================================ // Closures Chapter from From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/au/jEUH0.l // Closures are self-contained blocks of functionality that can be passed around and used in your code. Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages. // Closure Expressions // The Sort Function let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] func backward(s1: String, s2: String) -> Bool { return s1 > s2 } var reversedNames = names.sorted(by: backward) // Closure Expression Syntax reversedNames = names.sorted(by: { (s1:String, s2: String) -> Bool in return s1 > s2 }) // Inferring Type from from Context reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 }) // Implicit returns from Single-Expression Closures reversedNames = names.sorted(by: { s1, s2 in s1 > s2 }) // Shorthand Argument Names reversedNames = names.sorted(by: { $0 > $1 }) // Operator Functions reversedNames = names.sorted(by: >) // Trailing Closures func someFunctionThatTakesAClosure(closure: () -> ()) { } someFunctionThatTakesAClosure(closure: {}) someFunctionThatTakesAClosure() { } reversedNames = names.sorted() { $0 > $1 } reversedNames = names.sorted { $0 > $1 } let digitNames = [ 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4:"Four", 5: "Five", 6:"Six", 7: "Seven", 8: "Eight", 9: "Nine" ] let numbers = [16, 58, 510] let strings = numbers.map { (number) -> String in var number = number var output = "" repeat { output = digitNames[number % 10]! + output number /= 10 } while number > 0 return output } strings // Capturing Values func makeIncrementer(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementer() -> Int { runningTotal += amount return runningTotal } return incrementer } let incrementByTen = makeIncrementer(forIncrement: 10) incrementByTen() incrementByTen() incrementByTen() let incrementBySeven = makeIncrementer(forIncrement: 7) incrementBySeven() incrementByTen() // Closures are Reference Types let alsoIncrementByTen = incrementByTen alsoIncrementByTen() // Escaping Closures var completionHandlers: [() -> Void] = [] func soneFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) { completionHandlers.append(completionHandler) } func someFunctionWithNonescapingClosure(closure: () -> Void) { closure() } class SomeClass { var x = 10 func doSomething() { soneFunctionWithEscapingClosure { self.x = 100 } someFunctionWithNonescapingClosure { x = 200 } } } let instance = SomeClass() instance.doSomething() print(instance.x) // Prints "200" //: ## Autoclosures var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] print(customersInLine.count) let customerProvider = { customersInLine.remove(at: 0) } print(customersInLine.count) print("Now serving \(customerProvider())!") print(customersInLine.count) func serve(customer customerProvider: () -> String) { print("Now serving \(customerProvider())!") } serve(customer: { customersInLine.remove(at: 0) } ) //: Even though the first element of the customersInLine array is removed as part of the closure, that operation isn't carried out until the closure is actually called. If the closure is never called, the expression inside the closure is never evaluated. Note that the type of nextCustomer is not String but () -> String - a function that takes no arguments and returns a string. func serve(customer customerProvider: @autoclosure () -> String) { print("Now serving \(customerProvider())!") } serve(customer: customersInLine.remove(at: 0) ) //: The serveNextCustomer function above takes an explicit closure that returns the next customer's name. The version below performs the same operation but, instead uses an autoclosure. Now you can call the function as if it took a String argument instead of a closure. //: ### @autoclosure(escaping) var customerProviders: [() -> String] = [] func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) { customerProviders.append(customerProvider) } collectCustomerProviders(customersInLine.remove(at: 0)) collectCustomerProviders(customersInLine.remove(at: 0)) print("Collected \(customerProviders.count) closures.") for customerProvider in customerProviders { print("Now serving \(customerProvider())!") } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/07-Closures.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/08-Enumerations.playground/Contents.swift ================================================ // Enumerations // An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. enum CompassPoint { case north case south case east case west } enum Planet { case mercury, venus, earth, mars, jupiter, saturn, uranus, neptune } var directionToHead = CompassPoint.west directionToHead = .east // Matching Enumeration Values with a Switch Statement directionToHead = .south switch directionToHead { case .north: print("Lots of planets have a north") case .south: print("Watch out for penguins") case .east: print("Where the sun rises") case .west: print("Where the skies are blue") } let somePlanet = Planet.earth switch somePlanet { case .earth: print("Mostly Harmless") default: print("Not a safe place for humans") } // Associated Values enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } var productBarcode = Barcode.upc(8, 85909, 51226, 3) productBarcode = .qrCode("ABCDEFGHIJKLMNOP") switch productBarcode { case .upc(let numberSystem, let manufacturer, let product, let check): print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)") case .qrCode(let productCode): print("QR code: \(productCode).") } productBarcode = Barcode.upc(8, 85909, 51226, 3) switch productBarcode { case let .upc(numberSystem, manufacturer, product, check): print("UPC : \(numberSystem), \(manufacturer), \(product), \(check).") case let .qrCode(productCode): print("QR code: \(productCode).") } // Raw Values enum ASCIIControlCharacter: Character { case tab = "\t" case lineFeed = "\n" case carriageReturn = "\r" } // Implicitly Assigned Raw Values enum PlanetRaw: Int { case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune } let earthsOrder = PlanetRaw.earth.rawValue // earthsOrder is 3 enum CompassPointRaw: String { case north, south, east, west } let sunsetDirection = CompassPointRaw.west.rawValue // sunsetDirection is "West" // Initializing from a Raw Value let possiblePlanet = PlanetRaw(rawValue: 7) let positionToFind = 11 if let somePlanet = PlanetRaw(rawValue: positionToFind) { switch somePlanet { case .earth: print("Mostly harmless") default: print("Not a safe place for humans") } } else { print("There isn't a planet at position \(positionToFind)") } // Recursive Enumerations enum ArithmeticExpression { case number(Int) indirect case addition(ArithmeticExpression, ArithmeticExpression) indirect case multiplication(ArithmeticExpression, ArithmeticExpression) } indirect enum ArithmeticExpression2 { case number(Int) case addition(ArithmeticExpression2, ArithmeticExpression2) case multiplication(ArithmeticExpression2, ArithmeticExpression2) } let five = ArithmeticExpression.number(5) let four = ArithmeticExpression.number(4) let sum = ArithmeticExpression.addition(five, four) let product = ArithmeticExpression.multiplication(sum, ArithmeticExpression.number(2)) func evaluate(_ expression: ArithmeticExpression) -> Int { switch expression { case .number(let value): return value case let .addition(lhs, rhs): return evaluate(lhs) + evaluate(rhs) case let .multiplication(lhs, rhs): return evaluate(lhs) * evaluate(rhs) } } print(evaluate(product)) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/08-Enumerations.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/09-ClassesAndStructures.playground/Contents.swift ================================================ // Classes and Structures class SomeClasse { } struct SomeStruct { } struct Resolution { var width = 0 var height = 0 } class VideoMode { var resolution = Resolution() var interlaced = false var frameRate = 0.0 var name: String? } // Class and Structure Instances let someResolution = Resolution() let someVideoMode = VideoMode() print("The width of someResolution is \(someResolution.width)") print("The width of someVideoMode is \(someVideoMode.resolution.width)") someVideoMode.resolution.width = 1280 print("The width of someVideoMode is now \(someVideoMode.resolution.width)") // Memberwise Initializers for Structure Types // All structures have an automatically-generated memberwise initializer, which you can use to initialize the member properties of new structure instances. let vga = Resolution(width: 640, height: 480) // Structures and Enumerations are Value Types // A value type is a type that is copied when it is assigned to a variable or constant, or when it is passed to a function. let hd = Resolution(width: 1920, height: 1080) var cinema = hd cinema.width = 2048 print("cinema is now \(cinema.width) pixels wide") print("hd is still \(hd.width) pixels wide") enum CompassPoint { case noth, south, east, west } var currentDirection = CompassPoint.west let rememberedDirection = currentDirection currentDirection = .east if rememberedDirection == .west { print("The remembered direction is still .west") } // Classes are Reference Types // Reference types are not copied when they are assigned to a variable or constant, or when they are passed to a function. Rather than a copy, a reference to the same existing instance is used instead. let tenEighty = VideoMode() tenEighty.resolution = hd tenEighty.interlaced = true tenEighty.name = "1080i" tenEighty.frameRate = 25.0 let alsoTenEighty = tenEighty alsoTenEighty.frameRate = 30.0 print("The frameRate property of tenEighty is now \(tenEighty.frameRate)") // Identity Operators if tenEighty === alsoTenEighty { print("tenEighty and alsoTenEighty refer to the same VideoMode instance.") } // Note that “identical to” (represented by three equals signs, or ===) does not mean the same thing as “equal to” (represented by two equals signs, or ==): // Pointers // A Swift constant or variable that refers to an instance of some reference type is similar to a pointer in C, but is not a direct pointer to an address in memory. // Choosing Between Classes and Structures // Assignment and Copy Behaviour for Dictionaries ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/09-ClassesAndStructures.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/10-Properties.playground/Contents.swift ================================================ // Properties // Stored Properties struct FixedLengthRange { var firstValue: Int let length: Int } var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3) rangeOfThreeItems.firstValue = 6 // Stored Properties of Constant Structure Instances // 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: let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4) //rangeOfFourItems.firstValue = 6 // The above line will report and error, even though firstValue is a variable property // Lazy Stored Properties class DataImporter { /* DataImporter is a class to import data from an external file. The class is assumed to take a non-trivial amount of time to initialize */ var fileName = "data.txt" // the Data Importer class would provide data importing functionality here } class DataManager { lazy var importer = DataImporter() var data = [String]() // the DataManager class would provide data management functionality here } let manager = DataManager() manager.data += ["Some data"] manager.data += ["Some more data"] // the DataImporter instance for the importer property has not yet been created print(manager.importer.fileName) // the DataImporter instance for the importer property has now been created // Computed Properties struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct Rect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set(newCenter) { origin.x = newCenter.x - (size.width / 2) origin.y = newCenter.y - (size.height / 2) } } } var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0)) let initialSquareCenter = square.center square.center = Point(x: 15.0, y: 15.0) print("square.origin is now at (\(square.origin.x), \(square.origin.y))") // Shorthand Setter Declaration // If no name is given for the new value a variable of name newValue is autogenerated struct AlternativeRect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } } // Read only Computed Properties struct Cuboid { var width = 0.0, height = 0.0, depth = 0.0 var volume: Double { return width * height * depth } } let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0) print("the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)") // Property Observers class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } didSet { if totalSteps > oldValue { print("Added \(totalSteps - oldValue) steps") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = 200 stepCounter.totalSteps = 360 stepCounter.totalSteps = 896 // Type Properties // Type properties are useful for defining values that are universal to all instances of a particular type, such as a constant property that all instances can use (like a static constant in C), or a variable property that stores a value that is global to all instances of that type (like a static variable in C). // Type Property Syntax struct SomeStructure { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 1 } } enum SomeEnumeration { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 6 } } class SomeClass { static var storedTypeProperty = "Some value." static var computedTypeProperty: Int { return 27 } class var overrideableComputedTypeProperty: Int { return 107 } } // Querying and setting Type Properties print(SomeStructure.storedTypeProperty) // prints "Some value." SomeStructure.storedTypeProperty = "Another value." print(SomeStructure.storedTypeProperty) // prints "Another value." print(SomeEnumeration.computedTypeProperty) // prints "6" print(SomeClass.computedTypeProperty) // prints "27" struct AudioChannel { static let thresholdLevel = 10 static var maxInputLevelForAllChannels = 0 var currentLevel: Int = 0 { didSet { if currentLevel > AudioChannel.thresholdLevel { // cap the new audio level to the threshold level currentLevel = AudioChannel.thresholdLevel } if currentLevel > AudioChannel.maxInputLevelForAllChannels { // store this as the new overall maximum input level AudioChannel.maxInputLevelForAllChannels = currentLevel } } } } var leftChannel = AudioChannel() var rightChannel = AudioChannel() leftChannel.currentLevel = 7 print(leftChannel.currentLevel) print(AudioChannel.maxInputLevelForAllChannels) rightChannel.currentLevel = 11 print(rightChannel.currentLevel) print(AudioChannel.maxInputLevelForAllChannels) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/10-Properties.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/11-Methods.playground/Contents.swift ================================================ // Methods Chapter // Instance Methods class Counter { var count = 0 func increment() { count += 1 } func increment(by amount: Int) { count += amount } func reset() { count = 0 } } let counter = Counter() counter.increment() counter.increment(by:5) counter.reset() // The self Property // Every instance of a type has an implicit property called self, which is exactly equivalent to the instance itself. You use this implicit self property to refer to the current instance within its own instance methods. struct Point { var x = 0.0, y = 0.0 func isToTheRightOf(x: Double) -> Bool { return self.x > x } } let somePoint = Point(x: 4.0, y: 5.0) if somePoint.isToTheRightOf(x: 1.0) { print("This point is to the right of the line where x == 1.0") } // Modifying Value TYpes from Within // Instance Methods // if you need to modify the properties of your structure or enumeration within a particular method, you can opt in to mutating behavior for that method. struct Point2 { var x = 0.0, y = 0.0 mutating func moveBy(x deltaX: Double, y deltaY:Double) { x += deltaX y += deltaY } } var somePoint2 = Point2(x: 1.0, y: 1.0) somePoint2.moveBy(x:2.0, y:3.0) print("The point is now at (\(somePoint2.x), \(somePoint2.y))") let fixedPoint = Point2(x: 3.0, y: 3.0) //fixedPoint.moveByX(2.0, y: 3.0) // this will report an error because fixedPoint is a constant // Assigning to self Within a Mutating Method struct Point3 { var x = 0.0, y = 0.0 mutating func moveByX(deltaX: Double, y deltaY: Double) { self = Point3(x: x + deltaX, y: y + deltaY) } } // Mutating methods for enumerations can set the implicit self parameter to be a different member from the same enumeration: enum TriStateSwitch { case off, low, high mutating func next() { switch self { case .off: self = .low case .low: self = .high case .high: self = .off } } } var ovenLight = TriStateSwitch.low ovenLight.next() ovenLight.next() // Type Methods class SomeClass { class func someTypeMethod() { // type method implementation goes here } } SomeClass.someTypeMethod() struct LevelTracker { static var highestUnlockedLevel = 1 var currentLevel = 1 static func unlock(_ level: Int) { if level > highestUnlockedLevel { highestUnlockedLevel = level } } static func isUnlocked(_ level: Int) -> Bool { return level <= highestUnlockedLevel } @discardableResult mutating func advance(to level: Int) -> Bool { if LevelTracker.isUnlocked(level) { currentLevel = level return true } else { return false } } } class Player { var tracker = LevelTracker() let playerName: String func complete(level: Int) { LevelTracker.unlock(level + 1) tracker.advance(to: level + 1) } init(name: String) { playerName = name } } var player = Player(name: "Argyrios") player.complete(level: 1) print("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)") player = Player(name: "Beto") if player.tracker.advance(to: 6) { print("player is now on level 6") } else { print("level 6 has not yet been unlocked") } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/11-Methods.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/12-Subscripts.playground/Contents.swift ================================================ // Subscripts /* subscript(index: Int) -> Int { get { // return an appropriate subscript value here } set(newValue) { // perform a suitable setting action here } } */ struct TimesTable { let multiplier: Int subscript(index: Int) -> Int { return multiplier * index } } let threeTimesTable = TimesTable(multiplier: 3) print("six times three is \(threeTimesTable[6])") // Subscript Usage var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4] numberOfLegs["bird"] = 2 // Subscript Options struct Matrix { let rows: Int, columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } func indexIsValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } subscript(row: Int, column: Int) -> Double { get { assert(indexIsValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { assert(indexIsValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0, 1] = 1.5 matrix[1, 0] = 3.2 matrix //let someValue = matrix[2, 2] // Assertion triggered due to out of range access ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/12-Subscripts.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/13-Inheritance.playground/Contents.swift ================================================ // Inheritance // Base Class class Vehicle { var currentSpeed = 0.0 var description: String { return "traveling at \(currentSpeed) miles per hour" } func makeNoise() { // do nothing - an arbitrary vehicle doesn't necessarily make a noise } } let someVehicle = Vehicle() print("Vehicle: \(someVehicle.description)") class Bicycle: Vehicle { var hasBasket = false } let bicycle = Bicycle() bicycle.hasBasket = true bicycle.currentSpeed = 15.0 print("Bicycle: \(bicycle.description)") class Tandem: Bicycle { var currentNumberOfPassengers = 0 } let tandem = Tandem() tandem.hasBasket = true tandem.currentNumberOfPassengers = 2 tandem.currentSpeed = 22.0 print("Tandem: \(tandem.description)") // Overriding // Overriding methods class Train: Vehicle { override func makeNoise() { print("Choo Choo") } } let train = Train() train.makeNoise() //Overriding Properties class Car: Vehicle { var gear = 1 override var description: String { return super.description + " in gear \(gear)" } } let car = Car() car.currentSpeed = 25.0 car.gear = 3 print("Car: \(car.description)") // Overriding Property Observers class AutomaticCar: Car { override var currentSpeed: Double { didSet{ gear = Int(currentSpeed / 10.0) + 1 } } } let automatic = AutomaticCar() automatic.currentSpeed = 35.0 print("AutomaticCar: \(automatic.description)") ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/13-Inheritance.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/14-Initialization.playground/Contents.swift ================================================ // Initialization struct Fahrenheit { var temperature: Double init() { temperature = 32.0 } } var f = Fahrenheit() print("The default temperature is \(f.temperature)° Fahrenheit") // Customizing Initialization // Initialization Parameters struct Celsius { var temperatureInCelsius: Double init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } } let boilingPointOfWater = Celsius(fromFahrenheit: 212.0) let freezingPointOfWater = Celsius(fromKelvin: 273.15) // Parameter names and Argument Labels struct Color { let red, green, blue: Double init(red: Double, green: Double, blue: Double) { self.red = red self.green = green self.blue = blue } init(white: Double) { red = white green = white blue = white } } let magenta = Color(red: 1.0, green: 0.0, blue: 1.0) let halfGray = Color(white: 0.5) //let verGreen = Color(0.0, 1.0, 0.0) // Compile time error because external names for parameters were omitted // Initializer Parameters Without Argument Labels struct Celsius2 { var temperatureInCelsius: Double init(fromFahrenheit fahrenheit: Double) { temperatureInCelsius = (fahrenheit - 32) / 1.8 } init(fromKelvin kelvin: Double) { temperatureInCelsius = kelvin - 273.15 } init(_ celsius: Double) { temperatureInCelsius = celsius } } let bodyTemperature = Celsius2(37.0) // Optional Property Types class SurveyQuestion { var text: String var response: String? init(text: String) { self.text = text } func ask() { print(text) } } let cheeseQuestion = SurveyQuestion(text: "Do you like cheese?") cheeseQuestion.ask() cheeseQuestion.response = "Yes, I do like cheese." // Assigning Constant Properties during Initialization class SurveyQuestion2 { let text: String var response: String? init(text: String) { self.text = text } func ask() { print(text) } } let beetsQuestion = SurveyQuestion2(text: "How about beets?") beetsQuestion.ask() beetsQuestion.response = "I also like beets. (But not with cheese.)" // Default Initializer class ShoppingListItem { var name: String? var quantity = 1 var purchased = false } var item = ShoppingListItem() // Memberwise Initializers for Structure Types // Because both stored properties have a default value, the Size structure automatically receives an init(width:height:) memberwise initializer, which you can use to initialize a new Size instance: struct Size { var width = 0.0, height = 0.0 } let twoByTwo = Size(width: 2.0, height: 2.0) // Initializer Delegation for Value Types //struct Size2 { // var width = 0.0, height = 0.0 //} struct Point { var x = 0.0, y = 0.0 } struct Rect { var origin = Point() var size = Size() init() {} init(origin: Point, size: Size) { self.origin = origin self.size = size } init(center: Point, size: Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origin: Point(x: originX, y: originY), size: size) } } let basicRect = Rect() let originRect = Rect(origin: Point(x: 2.0, y: 2.0), size: Size(width: 5.0, height: 5.0)) let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height: 3.0)) // Class Inheritance and Initialization // Rule 1 // Designated initializers must call a designated initializer from their immediate superclass // Rule 2 // Convenience initializers must call another initializer available in the same class // Rule 3 // Convenience initializers must ultimately end up calling a designated initializer // Designated initializers must always delegate up. Convenience initializers must always delegate across // Initialization is a 2 stage process. There are several safety checks that the compiler performs // Safety Check 1 // A deignated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass // Safety Check 2 // A designated initializer must delegate up to a superclass initializer before assigning a value to an inherited property. If it doesn't, the new value the designated initializer assigns will be overwritten by the superclass as part of its own initialization // Safety Check 3 // A convenience initializer must delegate to another initializer before assigning a value to any property (including properties defined by the same class). If it doesn't, the new value the convenience initializer assigns will be overwritten by its own class's designated initializer. // Safety Check 4 // An initializer cannot call any instance methods, read the values of any instance properties, or refer to self as a value until after the first phase of initialization is complete. // Two-Phase initialization // Phase 1 // - A designated or convenience initializer is called on a class // - Memory for a new instance of that class is allocated. The memory is not yet initialized. // - 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. // - The designated initializer hands off to a superclass initializer to perform the same task for its own stored properties. // - This continues up the class inheritance chain until the top of the chain is reached. // - Once the top of the chain is reached, and the final class in the chain has ensured that all of its stored properties have a value, the instance's memory is considered to be fully initialized, and phase 1 is complete. // // Phase 2 // - Working back down from the top of the chain, each designated initializer in the chain has the option to customize the instance further. Initializers are now able to access self and can modify its properties, call its instance methods, and so on. // - Finally, any convenience initializers in the chain have the option to customize the instance and to work with self. // Initializer Inheritance and Overriding class Vehicle { var numberOfWheels = 0 var description: String { return "\(numberOfWheels) wheel(s)" } } let vehicle = Vehicle() print("Vehicle: \(vehicle.description)") class Bicycle: Vehicle { override init() { super.init() numberOfWheels = 2 } } let bicycle = Bicycle() print("Bicycle: \(bicycle.description)") // Automatic Initializers // Rule 1 // If your subclass doesn't define any designated initializers, it automatically inherits all of its superclass designated initializers // Rule 2 // If your subclass provides an implementaction of all of its superclass designated initializers- either by inheriting them as per rule 1, or by providing a custom implementation as part of its definitition- the it automatically inherits all of the superclass convenience initializers. // Designated and Convenience Initializers in Action class Food { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[Unnamed]") } } let namedMeat = Food(name: "Bacon") let mysteryMeat = Food() class RecipeIngredient: Food { var quantity: Int init(name: String, quantity: Int) { self.quantity = quantity super.init(name: name) } override convenience init(name: String) { self.init(name: name, quantity: 1) } } let oneMysteryItem = RecipeIngredient() let oneBacon = RecipeIngredient(name: "Bacon") let sixEggs = RecipeIngredient(name: "Eggs", quantity: 6) // In this example, the superclass for RecipeIngredient is Food, which has a single convenience initializer called init(). This initializer is therefore inherited by RecipeIngredient. The inherited version of init() functions in exactly the same way as the Food version, except that it delegates to the RecipeIngredient version of init(name: String) rather than the Food version. class ShoppingListItem2: RecipeIngredient { var purchased = false var description: String { var output = "\(quantity) x \(name)" output += purchased ? " √" : " ✘" return output } } // Because ShoppingListItem2 provides a default value for all of the properties it introduces and does not define any initializers itself, ShoppingListItem automatically inherits all of the designated and convenience initializers from its superclass. ShoppingListItem2(name: "Eggs, quantity: 6), var breakfastList = [ ShoppingListItem2(), ShoppingListItem2(name: "Bacon"), ShoppingListItem2(name: "Eggs", quantity: 6), ] breakfastList[0].name = "Orange juice" breakfastList[0].purchased = true for item in breakfastList { print(item.description) } // Failable Initializers #if swift(>=3.1) let wholeNumber: Double = 12345.0 let pi = 3.14159 if let valueMaintained = Int(exactly: wholeNumber) { print("\(wholeNumber) conversion to int maintains value") } let valueChanged = Int(exactly: pi) if valueChanged == nil { print("\(pi) conversion to int does not maintain value") } #endif struct Animal { let species: String init?(species: String) { if species.isEmpty { return nil } self.species = species } } let someCreature = Animal(species: "Giraffe") // is of type Animal?, not Animal if let giraffe = someCreature { print("An animal was initialized with a species of \(giraffe.species)") } let anonymousCreature = Animal(species: "") if anonymousCreature == nil { print("The anonymous creature could not be initialized") } // Failable Initializers for Enumerations enum TemperatureUnit { case Kelvin, Celsius, Fahrenheit init?(symbol: Character) { switch symbol { case "K": self = .Kelvin case "C": self = .Celsius case "F": self = .Fahrenheit default: return nil } } } let fahrenheitUnit = TemperatureUnit(symbol: "F") if fahrenheitUnit != nil { print("This is a defined temperature unit, so initialization succeeded.") } let unknownUnit = TemperatureUnit(symbol: "X") if unknownUnit == nil { print("This is not a defined temperature unit, so initialization failed.") } // Failable Initializers for Enumerations with Raw Values enum TempUnit: Character { case Kelvin = "K", Celsius = "C", Fahrenheit = "F" } let fahrUnit = TempUnit(rawValue:"F") if fahrUnit != nil { print("This is a defined temperature unit, so initialization succeeded.") } let unknownUnit2 = TempUnit(rawValue: "X") if unknownUnit2 == nil { print("This is not a defined temperature unit, so initialization failed.") } // Propagation of Initialization Failure // Failable initializers for value types can trigger failure at any point. For classes, however a failable initializer can trigger an initialization failure only after all stored properties introduced by that class have been set to an initial value. class Product { let name: String! init?(name: String) { if name.isEmpty { return nil } self.name = name } } class CartItem: Product { let quantity: Int init?(name: String, quantity: Int) { if quantity < 1 { return nil } self.quantity = quantity super.init(name: name) } } if let twoSocks = CartItem(name: "sock", quantity: 2) { print("Item: \(twoSocks.name), quantity: \(twoSocks.quantity)") } if let zeroShirts = CartItem(name: "shirt", quantity: 0) { print("Item: \(zeroShirts.name), quantity: \(zeroShirts.quantity)") } else { print("Unable to initialize zero shirts") } if let oneUnnamed = CartItem(name: "", quantity: 1) { print("Item: \(oneUnnamed.name), quantity: \(oneUnnamed.quantity)") } else { print("Unable to initialize one unnamed product") } // Overriding a Failable Initializer class Document { var name: String? // this initializer creates a document with a nil name value init() {} // this initializer creates a document with a non-empty name value init?(name: String) { if name.isEmpty { return nil } self.name = name } } class AutomaticallyNamedDocument: Document { override init() { super.init() self.name = "[Untitled]" } override init(name: String) { super.init() if name.isEmpty { self.name = "[Untitled]" } else { self.name = name } } } class UntitledDocument: Document { override init() { super.init(name: "[Untitled]")! } } // The init! Failable Initializer // Required Initializers class SomeClass { required init() { // Initializer implementation goes here } } class SomeSubclass: SomeClass { required init() { // subclass implementation of the required initializer goes here } } // Setting a default Property Value with a Closure or Function class SomeOtherClass { let someProperty: Int = { // create a default value for someProperty inside this closure // someValue must be of the same type as SomeType return 1234 }() } // Note that the closure’s end curly brace is followed by an empty pair of parentheses. This tells Swift to execute the closure immediately. If you omit these parentheses, you are trying to assign the closure itself to the property, and not the return value of the closure. struct Chessboard { let boardColors: [Bool] = { var temporaryBoard = [Bool]() var isBlack = false for i in 1...8 { for j in 1...8 { temporaryBoard.append(isBlack) isBlack = !isBlack } isBlack = !isBlack } return temporaryBoard }() func squareIsBlackAt(row: Int, column: Int) -> Bool { return boardColors[(row * 8) + column] } } let board = Chessboard() print(board.squareIsBlackAt(row: 0, column: 1)) print(board.squareIsBlackAt(row: 7, column: 7)) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/14-Initialization.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/15-Deinitialization.playground/Contents.swift ================================================ // Deinitialization Chapter // Class definitions can have at most one deinitializer per class. The deinitializer does not take any parameters and is written without parentheses: struct Bank { static var coinsInBank = 10_000 static func distribute(coins numberOfCoinsRequested: Int) -> Int { let numberOfCoinsToVend = min(numberOfCoinsRequested, coinsInBank) coinsInBank -= numberOfCoinsToVend return numberOfCoinsToVend } static func receive(coins: Int) { coinsInBank += coins } } class Player { var coinsInPurse: Int init(coins: Int) { coinsInPurse = Bank.distribute(coins: coins) } func win(coins: Int) { coinsInPurse += Bank.distribute(coins: coins) } deinit { Bank.receive(coins: coinsInPurse) } } var playerOne: Player? = Player(coins: 100) print("A new player has joined the game with \(playerOne!.coinsInPurse) coins") print("There are now \(Bank.coinsInBank) coins left in the bank") playerOne!.win(coins: 2_000) print("PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins") print("The bank now only has \(Bank.coinsInBank) coins left") playerOne = nil print("PlayerOne has left the game") print("The bank now has \(Bank.coinsInBank) coins") Bank.coinsInBank // This should be back to 10_000. The playerOne variable doesn't get deinitialized in the playground because the GUI keeps it around in case it is referred to again I presume. ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/15-Deinitialization.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/16-AutomaticReferenceCounting.playground/Contents.swift ================================================ // Automatic Reference Counting class Person { let name: String init(name: String) { self.name = name print("\(name) is being initialized") } deinit { print("\(name) is being deinitialized") } } var reference1: Person? var reference2: Person? var reference3: Person? reference1 = Person(name: "John Appleseed") reference2 = reference1 reference3 = reference1 reference1 = nil reference2 = nil reference3 = nil // We should see the message that the Person object has been deinitialized however due to the playground this has not occured. // Strong Reference cycles between Classes class Person2 { let name: String init(name: String) { self.name = name } var apartment: Apartment? deinit { print("\(name) is being deinitialized") } } class Apartment { let unit: String init(unit: String) { self.unit = unit } var tenant: Person2? deinit { print("Apartment #\(unit) is being deinitialized") } } var john: Person2? var unit4A: Apartment? john = Person2(name: "John Appleseed") unit4A = Apartment(unit: "4A") john!.apartment = unit4A unit4A!.tenant = john // Unfortunately, linking these two instances creates a strong reference cycle between them. The Person instance now has a strong reference to the Apartment instance, and the Apartment instance has a strong reference to the Person instance. Therefore, when you break the strong references held by the john and number73 variables, the reference counts do not drop to zero, and the instances are not deallocated by ARC: john = nil unit4A = nil // We have now leaked memory // Resolving Strong Reference Cycles between Class Instances // Use a weak reference whenever it is valid for that reference to become nil at some point during its lifetime. Conversely, use an unowned reference when you know that the reference will never be nil once it has been set during initialization. // Weak References class Person3 { let name: String init(name: String) { self.name = name } var apartment: Apartment3? deinit { print("\(name) is being deinitialized") } } class Apartment3 { let unit: String init(unit: String) { self.unit = unit } weak var tenant: Person3? deinit { print("Apartment #\(unit) is being deinitialized") } } var james: Person3? var number74: Apartment3? james = Person3(name: "James Appleseed") number74 = Apartment3(unit: "74") james!.apartment = number74 number74!.tenant = james james = nil number74 = nil // Unowned References class Customer { let name: String var card: CreditCard? init(name: String) { self.name = name } deinit { print("\(name) is being deinitialized") } } class CreditCard { let number: UInt64 unowned let customer: Customer init(number: UInt64, customer: Customer) { self.number = number self.customer = customer } deinit { print("Card #\(number) is being deinitialized") } } var justin: Customer? justin = Customer(name: "Justin McIntyre") justin!.card = CreditCard(number: 1234_5678_9012_3456, customer: justin!) justin = nil // Unowned References and Implicitly Unwrapped Optional Properties // Both properties should always have a value, and neither property should ever be nil once initialization is complete. This enables both properties to be accessed directly (without optional unwrapping) once initialization is complete, while still avoiding a reference cycle. class Country { let name: String var capitalCity: City! init(name: String, capitalName: String) { self.name = name self.capitalCity = City(name: capitalName, country: self) } } class City { let name: String unowned let country: Country init(name: String, country: Country) { self.name = name self.country = country } } // The initializer for City is called from within the initializer for Country. However, the initializer for Country cannot pass self to the City initializer until a new Country instance is fully initialized, as described in Two-Phase Initialization. To cope with this requirement, you declare the capitalCity property of Country as an implicitly unwrapped optional property, indicated by the exclamation mark at the end of its type annotation (City!). This means that the capitalCity property has a default value of nil, like any other optional, but can be accessed without the need to unwrap its value. var country = Country(name: "Canada", capitalName: "Ottawa") print("\(country.name)'s capital city is called \(country.capitalCity.name)") // Strong Reference Cycles for Closures class HTMLElement { let name: String let text: String? lazy var asHTML: () -> String = { if let text = self.text { return "<\(self.name)>\(text)" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is being deinitialized") } } let heading = HTMLElement(name: "h1") let defaultText = "some default text" heading.asHTML = { return "<\(heading.name)>\(heading.text ?? defaultText)" } print(heading.asHTML()) var paragraph: HTMLElement? = HTMLElement(name: "p", text: "hello, world") print(paragraph!.asHTML()) // Unfortunately, the HTMLElement class, as written above, creates a strong reference cycle between an HTMLElement instance and the closure used for its default asHTML value. paragraph = nil // Note that the message in the HTMLElement deinitializer is not printed, which shows that the HTMLElement instance is not deallocated. // Resolving Strong Reference Cycles for Closures /* @lazy var someClosure: (Int, String) -> String = { [unowned self] (index: Int, stringToProcess: String) -> String in // Closure body goes here } */ class HTMLElement2 { let name: String let text: String? lazy var asHTML: () -> String = { [unowned self] in if let text = self.text { return "<\(self.name)>\(text)" } else { return "<\(self.name) />" } } init(name: String, text: String? = nil) { self.name = name self.text = text } deinit { print("\(name) is being deinitialized") } } var paragraph2: HTMLElement2? = HTMLElement2(name: "p", text: "hello, world") print(paragraph2!.asHTML()) paragraph2 = nil // prints "p is being deinitialized" ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/16-AutomaticReferenceCounting.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/17-OptionalChaining.playground/Contents.swift ================================================ // Optional Chaining class Person { var residence: Residence? } class Residence { var numberOfRooms = 1 } let john = Person() //let roomCount = john.residence!.numberOfRooms // This triggers a runtime error if let roomCount = john.residence?.numberOfRooms { print("John's residence has \(roomCount) room(s).") } else { print("Unable to retreive the number of rooms.") } // Defining Model Classes for Optional Chaining class Person2 { var residence: Residence2? } class Residence2 { var rooms = [Room]() var numberOfRooms: Int { return rooms.count } subscript(i: Int) -> Room { return rooms[i] } func printNumberOfRooms() { print("The number of rooms is \(numberOfRooms)") } var address: Address? } class Room { let name: String init(name: String) { self.name = name } } class Address { var buildingName: String? var buildingNumber: String? var street: String? func buildingIdentifier() -> String? { if (buildingName != nil) { return buildingName } else if (buildingNumber != nil) { return buildingNumber } else { return nil } } } // Accessing Properties Through Optional Chaining let jack = Person2() if let roomCount = john.residence?.numberOfRooms { print("John's residence has \(roomCount) room(s).") } else { print("Unable to retreive the number of rooms.") } let someAddress = Address() someAddress.buildingNumber = "29" someAddress.street = "Acacia Road" jack.residence?.address = someAddress func createAddress() -> Address { print("Function was called.") let someAddress = Address() someAddress.buildingNumber = "29" someAddress.street = "Acacia Road" return someAddress } // Calling Methods through Optional Chaining if jack.residence?.printNumberOfRooms() != nil { print("It was possible to print the number of rooms.") } else { print("It was not possible to print the number of rooms.") } // printNumberOfRooms returns Void? if called on an optional parent value if (jack.residence?.address = someAddress) != nil { print("It was possible to set the address.") } else { print("It was not possible to set the address.") } // Prints "It was not possible to set the address." // Accessing Subscripts Through Optional Chaining if let firstRoomName = jack.residence?[0].name { print("The first room name is \(firstRoomName).") } else { print("Unable to retrieve the first room name.") } //jack.residence?[0] = Room(name: "Bathroom") //This subscript setting attempt also fails, because residence is currently nil. let jacksHouse = Residence2() jacksHouse.rooms.append(Room(name: "Living Room")) jacksHouse.rooms.append(Room(name: "Kitchen")) jack.residence = jacksHouse if let firstRoomName = jack.residence?[0].name { print("The first room name is \(firstRoomName).") } else { print("Unable to retrieve the first room name.") } // Accessing Subscripts of Optional Type var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]] testScores["Dave"]?[0] = 91 testScores["Bev"]?[0] += 1 testScores["Brian"]?[0] = 72 // Fails as no Brian testScores // Linking Multiple levels of Chaining if let jacksStreet = jack.residence?.address?.street { print("Jack's street name is \(jacksStreet).") } else { print("Unable to retrieve the address.") } let jacksAddress = Address() jacksAddress.buildingName = "The Larches" jacksAddress.street = "Laurel Street" jack.residence!.address = jacksAddress if let jacksStreet = jack.residence?.address?.street { print("Jack's street name is \(jacksStreet).") } else { print("Unable to retrieve the address.") } // Chaining on Methods With Optional Return Values if let buildingIdentifier = jack.residence?.address?.buildingIdentifier() { print("Jack's building identifier is \(buildingIdentifier).") } if let beginsWithThe = jack.residence?.address?.buildingIdentifier()?.hasPrefix("The") { if beginsWithThe { print("Jack's building identifier begins with \"The\".") } else { print("Jack's building identifier does not begin with \"The\".") } } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/17-OptionalChaining.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/18-ErrorHandling.playground/Contents.swift ================================================ import Cocoa //: # Error Handling //: Swift provides first-class support for throwing, catching, propagating, and manipulating recoverable errors at runtime (NOTE: recoverable). //: //: ## Representing and Throwing Errors enum VendingMachineError: Error { case invalidSelection case insufficientFunds(coinsNeeded: Int) case outOfStock } // throw VendingMachineError.InsufficientFunds(required: 5) //: ## Handling Errors //: ### Propagating Errors using Throwing Functions func canThrowErrors() throws -> String { return "" } func cannotThrowErrors() -> String { return "" } struct Item { var price: Int var count: Int } class VendingMachine { var inventory = [ "Candy Bar": Item(price: 12, count: 7), "Chips": Item(price: 10, count: 4), "Pretzels": Item(price: 7, count: 11) ] var coinsDeposited = 0 func vend(itemNamed name: String) throws { guard let item = inventory[name] else { throw VendingMachineError.invalidSelection } guard item.count > 0 else { throw VendingMachineError.outOfStock } guard item.price <= coinsDeposited else { throw VendingMachineError.insufficientFunds(coinsNeeded: item.price - coinsDeposited) } coinsDeposited -= item.price var newItem = item newItem.count -= 1 inventory[name] = newItem print("Dispensing \(name)") } } let favoriteSnacks = [ "Alice": "Chips", "Bob": "Licorice", "Eve": "Pretzels", ] func buyFavoriteSnack(person: String, vendingMachine: VendingMachine) throws { let snackName = favoriteSnacks[person] ?? "Candy Bar" try vendingMachine.vend(itemNamed: snackName) } //: Note that vend() must be marked with the try keyword. Also because the errors are not handled here the error is propagated up to buyFavoriteSnack() as noted by the throws keyword. struct PurchasedSnack { let name: String init(name: String, vendingMachine: VendingMachine) throws { try vendingMachine.vend(itemNamed: name) self.name = name } } //: ## Handling Errors Using Do-Catch var vendingMachine = VendingMachine() vendingMachine.coinsDeposited = 8 do { try buyFavoriteSnack(person: "Alice", vendingMachine: vendingMachine) // Enjoy delicious snack } catch VendingMachineError.invalidSelection { print("Invalid Selection") } catch VendingMachineError.outOfStock { print("Out of Stock") } catch VendingMachineError.insufficientFunds(let coinsNeeded) { print("Insufficient funds. Please insert an additional $\(coinsNeeded).") } //: ## Converting Errors to Optional Values //: If an error is thrown while evaluating the try? expression, the value of the expression is nil enum UnluckyError: Error { case unlucky } func someThrowingFunction() throws -> Int { let success = arc4random_uniform(5) if success == 0 { throw UnluckyError.unlucky } return Int(success) } let x = try? someThrowingFunction() let y: Int? do { y = try someThrowingFunction() } catch { y = nil } //: Try? lets you write concise error handling code when you want to handle all errors the same way. struct Data { } func fetchDataFromDisk() throws -> Data { let success = arc4random_uniform(5) if success == 0 { throw UnluckyError.unlucky } return Data() } func fetchDataFromServer() throws -> Data { let success = arc4random_uniform(5) if success == 0 { throw UnluckyError.unlucky } return Data() } func fetchData() -> Data? { if let data = try? fetchDataFromDisk() { return data } if let data = try? fetchDataFromServer() { return data } return nil } fetchData() //: ## Disabling Error Propagation //: Calling a throwing function or method with try! disables error propagation and wraps the call in a run-time assertion that no error will be thrown. If an error actually is thrown, you'll get a runtime error. //let photo = try! loadImage("./Resources/John Appleseed.jpg") //: ## Specifying Clean-Up Actions //: A defer statement defers execution until the current scope is exited. //: Deferred statements may not contain any code that would transfer control out of the statements, such as a break or return statement, or by throwing an error. //: Deferred actions are executed in reverse order of how they are specified. enum FileError: Error { case endOfFile case fileClosed } func exists(_ filename: String) -> Bool { return true } class FakeFile { var isOpen = false var filename = "" var lines = 100 func readline() throws -> String? { if self.isOpen { if lines > 0 { lines -= 1 return "line number \(lines) of text\n" } else { throw FileError.endOfFile //return nil } } else { throw FileError.fileClosed } } } func open(fileNamed: String) -> FakeFile { let file = FakeFile() file.filename = fileNamed file.isOpen = true print("\(file.filename) has been opened") return file } func close(file: FakeFile) { file.isOpen = false print("\(file.filename) has been closed") } func processFile(named: String) throws { if exists(named) { let file = open(fileNamed: named) defer { close(file: file) } while let line = try file.readline() { // Work with the file print(line) } // close(file) is called here, at the end of the scope. } } do { try processFile(named: "myFakeFile") } catch FileError.endOfFile { print("Reached the end of the file") } catch FileError.fileClosed { print("The file isn't open") } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/18-ErrorHandling.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/19-TypeCasting.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/19-TypeCasting.playground/section-1.swift ================================================ // Type Casting class MediaItem { var name: String init(name: String) { self.name = name } } class Movie: MediaItem { var director: String init(name: String, director: String) { self.director = director super.init(name: name) } } class Song: MediaItem { var artist: String init(name: String, artist: String) { self.artist = artist super.init(name: name) } } // Swift’s type checker is able to deduce that Movie and Song have a common superclass of MediaItem, and so it infers a type of MediaItem[] for the library array: let library = [ Movie(name: "Casablanca", director: "Michael Curtiz"), Song(name: "Blue Suede Shoes", artist: "ElvisPresley"), Movie(name: "Citizen Kane", director: "Orson Welles"), Song(name: "The One And Only", artist: "Chesney Hawkes"), Song(name: "Never Gonna Give You Up", artist: "Rick Astley") ] // The items stored in library are still Movie and Song instances behind the scenes. However, if you iterate over the contents of this array, the items you receive back are typed as MediaItem, and not as Movie or Song. In order to work with them as their native type, you need to check their type, or downcast them to a different type, as described below. // Checking Type var movieCount = 0 var songCount = 0 for item in library { if item is Movie { movieCount += 1 } else if item is Song { songCount += 1 } } print("Media library contains \(movieCount) movies and \(songCount) songs") // Downcasting for item in library { if let movie = item as? Movie { print("Movie: '\(movie.name)', dir. \(movie.director)") } else if let song = item as? Song { print("Song: '\(song.name)', by \(song.artist)") } } // Type Casting for Any and AnyObject var things = [Any]() things.append(0) things.append(0.0) things.append(42) things.append(3.1459) things.append("hello") things.append((3.0, 5.0)) things.append(Movie(name: "Ghostbusters", director: "Ivan Reitman")) things.append({ (name: String) -> String in "Hello, \(name)" }) for thing in things { switch thing { case 0 as Int: print("zero as an Int") case 0 as Double: print("zero as a Double") case let someInt as Int: print("an integer value of \(someInt)") case let someDouble as Double where someDouble > 0: print("a positive double value of \(someDouble)") case is Double: print("some other double value that I don't want to print") case let someString as String: print("a string value of \"\(someString)\"") case let (x, y) as (Double, Double): print("an (x, y) point at \(x), \(y)") case let movie as Movie: print("a movie called '\(movie.name)', dir. \(movie.director)") default: print("something else") } } // The cases of a switch statement use the forced version of the type cast operator (as, not as?) to check and cast to a specific type. This check is always safe within the context of a switch case statement. ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/20-NestedTypes.playground/Contents.swift ================================================ // Nested Types struct BlackjackCard { // nested Suit enumeration enum Suit: Character { case spades = "♠", hearts = "♡", diamonds = "♢", clubs = "♣" } // nestedRank enumeration enum Rank: Int { case two = 2, three, four, five, six, seven, eight, nine, ten case jack, queen, king, ace struct Values { let first: Int, second: Int? } var values: Values { switch self { case .ace: return Values(first: 1, second: 11) case .jack, .queen, .king: return Values(first: 10, second: nil) default: return Values(first: self.rawValue, second: nil) } } } // BlackjackCard properties and methods let rank: Rank, suit: Suit var description: String { var output = "suit is \(suit.rawValue)," output += " value is \(rank.values.first)" if let second = rank.values.second { output += " or \(second)" } return output } } let theAceOfSpades = BlackjackCard(rank: .ace, suit: .spades) print("theAceOfSpades: \(theAceOfSpades.description)") // Referring to Nested Types let heartsSymbol = BlackjackCard.Suit.hearts.rawValue print("heartsSymbol is \(heartsSymbol)") ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/20-NestedTypes.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/21-Extensions.playground/Contents.swift ================================================ // Extensions /* extension SomeType { // new functionality to add to SomeType goes here } extension SomeType: SomeProtocol, AnotherProtocol { // implementation of protocol requirements goes here } */ // Computed Properties extension Double { var km: Double { return self * 1_000.0 } var m: Double { return self } var cm: Double { return self / 100.0 } var mm: Double { return self / 1_000.0 } var ft: Double { return self / 3.28084 } } let oneInch = 25.4.mm print("One inch is \(oneInch) meters") let threeFeet = 3.ft print("Three feet is \(threeFeet) meters") let aMarathon = 42.km + 195.m print("A marathon is \(aMarathon) meters long") // Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties. // Initializers struct Size { var width = 0.0, height = 0.0 } struct Point { var x = 0.0, y = 0.0 } struct Rect { var origin = Point() var size = Size() } let defaultRect = Rect() let memberwiseRect = Rect(origin: Point(x: 2.0, y:2.0), size: Size(width: 5.0, height: 5.0)) extension Rect { init(center: Point, size: Size) { let originX = center.x - (size.width / 2) let originY = center.y - (size.height / 2) self.init(origin: Point(x: originX, y: originY), size: size) } } let centerRect = Rect(center: Point(x: 4.0, y: 4.0), size: Size(width: 3.0, height:3.0)) // Methods extension Int { func repetitions(task: () -> Void) { for _ in 0.. Int { var decimalBase = 1 for _ in 0.. 0: return .positive default: return .negative } } } func printIntegerKinds(_ numbers: [Int]) { for number in numbers { switch number.kind { case .negative: print("-") //print("- ", terminator: false) case .zero: print("0") //print("0 ", terminator: false) case .positive: print("+") //print("+ ", terminator: false) } } print("") } printIntegerKinds([3, 19, -27, 0, -6, 0, 7]) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/21-Extensions.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/22-Protocols.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/22-Protocols.playground/section-1.swift ================================================ // Protocols import Foundation /* protocol SomeProtocol { // protocol definition goes here } struct SomeStructure: FirstProtocol, AnotherProtocol { // structure definition goes here } // If a class has a superclass, list the superclass name before any protocols it adopts, followed by a comma: class SomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol { // class definition goes here } */ // Property Requirements // Property requirements are always declared as variable properties, prefixed with the var keyword. protocol SomeProtocol { var mustBeSettable: Int { get set } var doesNotNeedToBeSettable: Int { get } } // Always prefix type property requirements with the static keyword when you define them in a protocol. This is true even though type property requirements can be prefixed with the static or class keyword when implemented by a class: protocol AnotherProtocol { static var someTypeProperty: Int { get set } } // Here's an example of a protocol with a single instance property requirement: protocol FullyNamed { var fullName: String { get } } struct Person: FullyNamed { var fullName: String } let john = Person(fullName: "John AppleSeed") class Starship: FullyNamed { var prefix: String? var name: String init(name: String, prefix: String? = nil) { self.name = name self.prefix = prefix } var fullName: String { return ((prefix != nil ? prefix! + " " : "") + name) } } var ncc1701 = Starship(name: "Enterprise", prefix: "USS") // Method Requirements /* protocol SomeProtocol { static func someTypeMethod() } */ protocol RandomNumberGenerator { func random() -> Double } // linear congruential generator: class LinearCongruentialGenerator: RandomNumberGenerator { var lastRandom = 42.0 let m = 139968.0 let a = 3877.0 let c = 29573.0 func random() -> Double { lastRandom = ((lastRandom * a + c).truncatingRemainder(dividingBy:m)) return lastRandom / m } } let generator = LinearCongruentialGenerator() print("Here's a random number: \(generator.random())") print("And another one: \(generator.random())") // Mutating Method Requirements protocol Togglable { mutating func toggle() } enum OnOffSwitch: Togglable { case off, on mutating func toggle() { switch self { case .off: self = .on case .on: self = .off } } } var lightSwitch = OnOffSwitch.off lightSwitch.toggle() lightSwitch // Initializer Requirements // Protocols can require specific initializers to be implemented by conforming types. /* protocol SomeProtocol { init(someParameter: Int) } */ // Class Implementations of Protocol Initializer Requirements // You can implement a protocol initializer requirement on a conforming class as either a designated initializer or a convenience initializer. In both cases, you must mark the initializer implementation with the required modifier /* class SomeClass: SomeProtocol { required init(someParameter: Int) { // initializer implementation goes here } { */ // If a subclass overrides a designated initializer from a superclass, and also implements a matching initializer requirement from a protocol, mark the initializer implementation with both the required and override modifiers /* protocol SomeProtocol { init() } class SomeSuperClass { init() { // initializer implementation goes here } } class SomeSubClass: SomeSuperClass, SomeProtocol { // "required" from SomeProtocol conformance; "override" from SomeSuperClass required override init() { // initializer implementation goes here } } */ // Failable Initializer Requirements // Protocols as Types // Protocols do not actually implement any functionality themselves. Nonetheless, any protocol you create will become a fully-fledged type for use class Dice { let sides: Int let generator: RandomNumberGenerator init(sides: Int, generator: RandomNumberGenerator) { self.sides = sides self.generator = generator } func roll() -> Int { return Int(generator.random() * Double(sides)) + 1 } } var d6 = Dice(sides: 6, generator: LinearCongruentialGenerator()) for _ in 1...5 { print("Random dice roll is \(d6.roll())") } // Delegation protocol DiceGame { var dice: Dice { get } func play() } protocol DiceGameDelegate { func gameDidStart(_ game: DiceGame) func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) func gameDidEnd(_ game: DiceGame) } class SnakesAndLadders: DiceGame { let finalSquare = 25 let dice = Dice(sides: 6, generator:LinearCongruentialGenerator()) var square = 0 var board: [Int] init() { board = [Int](repeating: 0, count: finalSquare + 1) board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02 board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08 } var delegate: DiceGameDelegate? func play() { square = 0 delegate?.gameDidStart(self) gameLoop: while square != finalSquare { let diceRoll = dice.roll() delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll) switch square + diceRoll { case finalSquare: break gameLoop case let newSquare where newSquare > finalSquare: continue gameLoop default: square += diceRoll square += board[square] } } delegate?.gameDidEnd(self) } } class DiceGameTracker: DiceGameDelegate { var numberOfTurns = 0 func gameDidStart(_ game: DiceGame) { numberOfTurns = 0 if game is SnakesAndLadders { print("Started a new game of Snakes and Ladders") } print("The game is using a \(game.dice.sides)-sided dice") } func game(_ game: DiceGame, didStartNewTurnWithDiceRoll diceRoll: Int) { numberOfTurns += 1 print("Rolled a \(diceRoll)") } func gameDidEnd(_ game: DiceGame) { print("The game lasted for \(numberOfTurns) turns") } } let tracker = DiceGameTracker() let game = SnakesAndLadders() game.delegate = tracker game.play() // Adding Protocol Conformance with an Extension protocol TextRepresentable { var textualDescription: String { get } } extension Dice: TextRepresentable { var textualDescription: String { return "A \(sides)-sided dice" } } let d12 = Dice(sides: 12, generator: LinearCongruentialGenerator()) print(d12.textualDescription) d6.textualDescription extension SnakesAndLadders: TextRepresentable { var textualDescription: String { return "A game of Snakes and Ladders with \(finalSquare) squares" } } print(game.textualDescription) // Declaring Protocol Adoption with an Extension // If a type already conforms to all of the requirements of a protocol, but has not yet stated that it adopts that protocol, you can make it adopt the protocol with an empty extension: struct Hamster { var name: String var textualDescription: String { return "A hamster named \(name)" } } extension Hamster: TextRepresentable {} let simonTheHamster = Hamster(name: "Simon") let somethingTextRepresentable: TextRepresentable = simonTheHamster print(somethingTextRepresentable.textualDescription) // Collections of Protocol Types let things: [TextRepresentable] = [game, d12, simonTheHamster] for thing in things { print(thing.textualDescription) } // Note that the thing constant is of type TextRepresentable. It is not of type Dice, or DiceGame, or Hamster, even if the actual instance behind the scenes is of one of those types. // Protocol Inheritance /* protocol InheritingProtocol: SomeProtocol, Another Protocol { // protocol definition goes here } */ protocol PrettyTextRepresentable: TextRepresentable { var prettyTextualDescription: String { get } } // PrettyTextRepresentable must satisfy all of the requirements enforced by TextRepresentable, plus the additional requirements enforced by PrettyTextRepresentable. extension SnakesAndLadders: PrettyTextRepresentable { var prettyTextualDescription: String { var output = textualDescription + ":\n" for index in 1...finalSquare { switch board[index] { case let ladder where ladder > 0: output += "▲ " case let snake where snake < 0: output += "▼ " default: output += "○ " } } return output } } print(game.prettyTextualDescription) // Class-Only Protocols // You can limit protocol adoption to class types by adding the class keyword. /* protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol { // class-only protocol definition goes here } */ // Note: Use a class-only protocol when the behaviour defined by that protocol's requirements assumes or requires that a conforming type has reference semantics rather than value semantics. // Protocol Composition protocol Named { var name: String { get } } protocol Aged { var age: Int { get } } struct Person2: Named, Aged { var name: String var age: Int } func wishHappyBirthday(to celebrator: Named & Aged) { print("Happy birthday, \(celebrator.name), you're \(celebrator.age)!") } let birthdayPerson = Person2(name:"Malcom", age: 21) wishHappyBirthday(to: birthdayPerson) // Note: Protocol compositions do not define a new, permanent protocol type. Rather they define a temporary local protocol that has the combined requirements of all protocols in the composition. // Checking for Protocol Conformance protocol HasArea { var area: Double { get } } // You can check for protocol conformance only if your protocol is marked with the @objc attribute class Circle: HasArea { let pi = 3.1415927 var radius: Double var area: Double { return pi * radius * radius } init(radius: Double) { self.radius = radius } } class Country: HasArea { var area: Double init(area: Double) { self.area = area } } class Animal { var legs: Int init(legs: Int) { self.legs = legs } } let objects: [AnyObject] = [ Circle(radius: 2.0), Country(area: 243_610), Animal(legs: 4) ] for object in objects { if let objectWithArea = object as? HasArea { print("Area is \(objectWithArea.area)") } else { print("Something that doesn't have an area") } } // Note that the underlying objects are not changed by the casting process. They continue to be a Circle, a Country and an Animal. However, at the point that they are stored in the objectWithArea constant, they are only known to be of type HasArea, and so only their area property can be accessed. // Optional Protocol Requirements // Optional property requirements, and optional method requirements that return a value, will always return an optional value of the appropriate type when they are accessed or called, to reflect the fact that the optional requirement may not have been implemented. @objc protocol CounterDataSource { @objc optional func increment(forCount count: Int) -> Int @objc optional var fixedIncrement: Int { get } } class Counter { var count = 0 var dataSource: CounterDataSource? func increment() { if let amount = dataSource?.increment?(forCount: count) { count += amount } else if let amount = dataSource?.fixedIncrement { count += amount } } } class ThreeSource: NSObject, CounterDataSource { let fixedIncrement = 3 } var counter = Counter() counter.dataSource = ThreeSource() for _ in 1...4 { counter.increment() print(counter.count) } @objc class TowardsZeroSource: NSObject, CounterDataSource { func increment(forCount count: Int) -> Int { if count == 0 { return 0 } else if count < 0 { return 1 } else { return -1 } } } counter.count = -4 counter.dataSource = TowardsZeroSource() for _ in 1...5 { counter.increment() print(counter.count) } // Protocol Extensions // Protocols can be extended to procide method and property implementations to conforming types. This allows you to define behaviour on protocols themselves, rather than in each type's individual conformance or in a global function. // For example, the RandomNumberGenerator protocol can be extended to provide a randomBool() method, which uses the result of the required random() method to return a random Bool value: extension RandomNumberGenerator { func randomBool() -> Bool { return random() > 0.5 } } // By creating an extension on the protocol, all conforming types automatically gain this method implementation without and additional modification. //let generator2 = LinearCongruentialGenerator() //print("Here's a random number: \(generator2.random())") print("Here's a random Boolean: \(generator.randomBool())") // Providing Default Implementations // Protocol extensions can provide default implementations to any method or property requirement // If a conforming type provides its own implementation that is used instead. extension PrettyTextRepresentable { var prettyTextualDescription: String { return textualDescription } } extension Hamster: PrettyTextRepresentable { } print(simonTheHamster.prettyTextualDescription) // Adding Constraints to Protocol Extensions // You can specify constraints that conforming types must satisfy before methods and properties of an extension are available. // You use the where clause after the name of the protocol you are extending. extension Collection where Iterator.Element : TextRepresentable { var textualDescription: String { let itemsAsText = self.map { $0.textualDescription } return "[" + itemsAsText.joined(separator: ", ") + "]" } } let murrayTheHamster = Hamster(name: "Murray") let morganTheHamster = Hamster(name: "Morgan") let mauriceTheHamster = Hamster(name: "Maurice") let hamsters = [murrayTheHamster, morganTheHamster, mauriceTheHamster] // Because Array conforms to CollectionType, and the array's elements conform to the TextRepresentable protocol, the array can use the asList() method to get a textual representation of its contents: print(hamsters.textualDescription) ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/23-Generics.playground/Contents.swift ================================================ // Generics // The Problem That Generics Solve // standard, non-generic function func swapTwoInts(_ a: inout Int, _ b: inout Int) { let temporaryA = a a = b b = temporaryA } var someInt = 3 var anotherInt = 107 swapTwoInts(&someInt, &anotherInt) print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") // The swapTwoInts function is useful, but it can only be used with Int values. If you want to swap two String values, or two Double values, you have to write more functions, such as the swapTwoStrings and swapTwoDoubles functions shown below func swapTwoStrings(_ a: inout String, _ b: inout String) { let temporaryA = a a = b b = temporaryA } func swapTwoDoubles(_ a: inout Double, _ b: inout Double) { let temporaryA = a a = b b = temporaryA } // Generic Functions func swapTwoValues(_ a: inout T, _ b: inout T) { let temporaryA = a a = b b = temporaryA } swapTwoValues(&someInt, &anotherInt) print("someInt is now \(someInt), and anotherInt is now \(anotherInt)") var someString = "hello" var anotherString = "world" swapTwoValues(&someString, &anotherString) print("someString is now \(someString), and anotherString is now \(anotherString)") // Generic Types // Non-generic version of a Stack first struct IntStack { var items = [Int]() mutating func push(_ item: Int) { items.append(item) } mutating func pop() -> Int { return items.removeLast() } } // Now a Generic version struct Stack { var items = [Element]() mutating func push(_ item: Element) { items.append(item) } mutating func pop() -> Element { return items.removeLast() } } var stackOfStrings = Stack() stackOfStrings.push("uno") stackOfStrings.push("dos") stackOfStrings.push("tres") stackOfStrings.push("cuatro") stackOfStrings let fromTheTop = stackOfStrings.pop() // Extending a Generic Type extension Stack { var topItem: Element? { return items.isEmpty ? nil : items[items.count - 1] } } if let topItem = stackOfStrings.topItem { print("The top item on the stack is \(topItem).") } // Type Constraints /* func someFunction(someT: T, someU: U) { // function body goes here } */ func findIndex(ofString valueToFind: String, in array: [String]) -> Int? { for (index, value) in array.enumerated() { if value == valueToFind { return index } } return nil } let strings = ["cat", "dog", "llama", "parakeet", "terrapin"] if let foundIndex = findIndex(ofString: "llama", in: strings) { print("The index of llama is \(foundIndex)") } func findIndex(of valueToFind: T, in array: [T]) -> Int? { for (index, value) in array.enumerated() { if value == valueToFind { return index } } return nil } let doubleIndex = findIndex(of: 9.3, in: [3.14159, 0.1, 0.25]) let stringIndex = findIndex(of: "Andrea", in: ["Mike", "Malcolm", "Andrea"]) // Associated Types protocol Container { associatedtype Item mutating func append(_ item: Item) var count: Int { get } subscript(i: Int) -> Item { get } } struct IntStack2: Container { // original IntStack implementation var items = [Int]() mutating func push(_ item: Int) { items.append(item) } mutating func pop() -> Int { return items.removeLast() } // conformance to the Container protocol typealias Item = Int mutating func append(_ item: Int) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> Int { return items[i] } } struct Stack2: Container { // original Stack implementation var items = [Element]() mutating func push(_ item: Element) { items.append(item) } mutating func pop() -> Element { return items.removeLast() } // conformance to the Container protocol mutating func append(_ item: Element) { self.push(item) } var count: Int { return items.count } subscript(i: Int) -> Element { return items[i] } } // Extending an Existing Type to Specify an Associated Type extension Array: Container {} // Generic Where Clauses func allItemsMatch (_ someContainer: C1, _ anotherContainer: C2) -> Bool where C1.Item == C2.Item, C1.Item: Equatable { // check that both containers contain the same number of items if someContainer.count != anotherContainer.count { return false } // check each pair of items it see if they are equivilent for i in 0..() stackOfStrings2.push("uno") stackOfStrings2.push("dos") stackOfStrings2.push("tres") var arrayOfStrings = ["uno", "dos", "tres"] if allItemsMatch(stackOfStrings2, arrayOfStrings) { print("All items match.") } else { print("Not all items match.") } // Extensions with a Generic Where Clause extension Stack2 where Element: Equatable { func isTop(_ item: Element) -> Bool { guard let topItem = items.last else { return false } return topItem == item } } if stackOfStrings2.isTop("tres") { print("Top element is tres.") } else { print("Top element is something else.") } // If you try to call the isTop(_:) method on a stack whose elements aren't equatable, you'll get a compile-time error. struct NotEquatable { } var notEquatableStack = Stack2() let notEquatableValue = NotEquatable() notEquatableStack.push(notEquatableValue) // notEquatableStack.isTop(notEquatableValue) // Error extension Container where Item: Equatable { func startsWith(_ item: Item) -> Bool { return count >= 1 && self[0] == item } } if [9, 9, 9].startsWith(42) { print("Starts with 42.") } else { print("Starts with something else.") } extension Container where Item == Double { func average() -> Double { var sum = 0.0 for index in 0.. Item { get } associatedtype Iterator: IteratorProtocol where Iterator.Element == Item func makeIterator() -> Iterator } protocol ComparableContainer: Container where Item: Comparable { } // Generic Subscripts extension Container { subscript(indices: Indices) -> [Item] where Indices.Iterator.Element == Int { var result = [Item]() for index in indices { result.append(self[index]) } return result } } ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/23-Generics.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/24-AccessControl.playground/Contents.swift ================================================ // Access Control // You can assign specific access levels to individual types (classes, structures, and enumerations), as well as to properties, methods, initializers, and subscripts belonging to those types. Protocols can be restricted to a certain context, as can global constants, variables, and functions. // Modules and Source Files // A module is a single unit of code distribution - a framework or application. Something that can be imported // Access Levels // Public - Available anywhere. Used for defining the public interface. // Internal - Use within any source file within a module. // Private - Use only within the defining source file // No entity can be defined in terms of another entity that has a lower (more restrictive) access level. // Default Access level - Internal // Access Control Syntax public class SomePublicClass {} internal class SomeInternalClass {} fileprivate class SomeFilePrivateClass {} private class SomePrivateClass {} public var somePublicVariable = 0 internal let someInternalConstant = 0 fileprivate func someFilePrivateFunction() {} private func somePriviateFunction() {} class SomeImplicitlyInternalClass {} // implicitly internal let someImplicitlyInternalConstant = 0 // implicitly internal public class AnotherPublicClass { // explicitly public class public var somePublicProperty = 0 // explicitly public class member var someInternalProperty = 0 // implicitly internal class member private func somePrivateMethod() {} // explicitly private class member } class AnotherInternalClass { // implicitly internal class var someInternalProperty = 0 // implicitly internal class member private func somePrivateMethod() {} // explicitly private class member } fileprivate class AnotherFilePrivateClass { // explicitly file-private class func someFilePrivateMethod() {} // inplicitly file-private method private func somePrivateMethod() {} // explicitly file-private method } private class AnotherPrivateClass { // explicitly private class var somePrivateProperty = 0 // implicitly private class member func somePrivateMethod() {} // implicitly private class member } // Tuple Types // Tuples don't have a way to explicitly set their access level. Instead the tuples access level is set from the most restrictive access level of its components // Function Types // The access level of a function is set as the most restrictive access level of the function arguments and return type. You also must explicitly set the access level of the function type if it doesn't match the default /* func someFunction() -> (SomeInternalClass, SomePrivateClass) { // function implementation goes here } The function above won't compile because the SomePrivateClass sets the function type to private which is not explicitly set. */ private func someFunction() -> (SomeInternalClass, SomePrivateClass) { // function implementation goes here return (SomeInternalClass(), SomePrivateClass()) } // Enumeration Types // The individual cases of an enumeration have the same access level as the enum private enum CompassPoint { case north case south case east case west } // Subclasses // A subclass cannot have a higher access level than its superclass. // An override can make an inherited class member more accessible than its superclass. public class A { fileprivate func someMethod() {} } internal class B: A { override internal func someMethod() {} } public class C { fileprivate func someMethod() {} } internal class D: C { override internal func someMethod() { super.someMethod() } } // Constants, Variables, Properties and Subscripts // A constant, variable or property cannot be more public than its type. private var privateInstance = SomePrivateClass() // Getters and Setters // Below, we have a value string that is internal. We also have a numberOfEdits variable that tracks how many times value has been modified. numberOfEdits is effectively readonly from outside the class because its setter is marked as private. struct TrackedString { private(set) var numberOfEdits = 0 var value: String = "" { didSet { numberOfEdits += 1 } } } var stringToEdit = TrackedString() stringToEdit.value = "This string will be tracked." stringToEdit.value += " This edit will increment numberOfEdits." stringToEdit.value += " So will this one." print("The number of edits is \(stringToEdit.numberOfEdits)") stringToEdit.numberOfEdits // Initializers // Default initialisers are given the same access level as their type except that public types get given internal initializers. You can provide a public initializer if you need one. ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/24-AccessControl.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/25-AdvancedOperators.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/25-AdvancedOperators.playground/section-1.swift ================================================ // Advanced Operators // Unlike arithmetic operators in C, arithmetic operators in Swift do not overflow by default. Overflow behavior is trapped and reported as an error. To opt in to overflow behavior, use Swift’s second set of arithmetic operators that overflow by default, such as the overflow addition operator (&+). All of these overflow operators begin with an ampersand (&). // Bitwise Operators // Bitwise NOT let initialBits: UInt8 = 0b00001111 let invertedBits = ~initialBits // Bitwise AND let firstSixBits: UInt8 = 0b11111100 let lastSixBits: UInt8 = 0b00111111 let middleFourBits = firstSixBits & lastSixBits // Bitwise OR let someBits: UInt8 = 0b10110010 let moreBits: UInt8 = 0b01011110 let combinedBits = someBits | moreBits // Bitwise XOR let firstBits: UInt8 = 0b00010100 let otherBits: UInt8 = 0b00000101 let outputBits = firstBits ^ otherBits // Bitwise Left and Right Shift let shiftBits: UInt8 = 4 shiftBits << 1 shiftBits << 2 shiftBits << 5 shiftBits << 6 shiftBits >> 2 let pink: UInt32 = 0xCC6699 let redComponent = (pink & 0xFF0000) >> 16 let greenComponent = (pink & 0x00FF00) >> 8 let blueComponent = pink & 0x0000FF let negativeBits: Int8 = -4 negativeBits << 1 negativeBits << 2 negativeBits << 5 negativeBits << 6 negativeBits >> 2 negativeBits >> 5 // Doesn't overflow // Overflow Operators // Overflow addition (&+) // Overflow subtraction (&-) // Overflow multiplication (&*) var potentialOverflow = Int16.max // potentialOverflow += 1 // This causes an error if it runs var willOverflow = UInt8.max willOverflow = willOverflow &+ 1 // Value Underflow var unsignedOverflow = UInt8.min unsignedOverflow = unsignedOverflow &+ 1 unsignedOverflow = UInt8.min unsignedOverflow = unsignedOverflow &- 1 var signedOverflow = Int8.min signedOverflow = signedOverflow &- 1 // Precedence and Associativity // Operator associativity defines how operators of the same precedence are grouped together (or associated)—either grouped from the left, or grouped from the right. Think of it as meaning “they associate with the expression to their left,” or “they associate with the expression to their right. 2 + 3 * 4 % 5 // * and % have a higher precedence than +. // * and & have the same precendence as each other but both associate to their left. Think of this as adding implicit parentheses around these parts of the expression, starting from their left: (This explanation seems arbitrary to me. Aparently more info in the Expressions chapter) // Operator Functions // Infix Operators struct Vector2D { var x = 0.0, y = 0.0 } extension Vector2D { static func + (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y + right.y) } } let vector = Vector2D(x: 3.0, y: 1.0) let anotherVector = Vector2D(x: 2.0, y:4.0) let combinedVector = vector + anotherVector // Prefix and Postfix Operators extension Vector2D { static prefix func - (vector: Vector2D) -> Vector2D { return Vector2D(x: -vector.x, y: -vector.y) } } let positive = Vector2D(x: 3.0, y: 4.0) let negative = -positive let alsoPositive = -negative // Compound Assignment Operators extension Vector2D { static func += (left: inout Vector2D, right: Vector2D) { left = left + right } } var original = Vector2D(x: 1.0, y: 2.0) let vectorToAdd = Vector2D(x: 3.0, y: 4.0) original += vectorToAdd // It is not possible to overload the default assignment operator (=). Only the compound assignment operators can be overloaded. Similarly, the ternary conditional operator (a ? b : c) cannot be overloaded. // Equivalence Operators // Custom classes and structures do not receive a default implementation of the equivalence operators, known as the “equal to” operator (==) and “not equal to” operator (!=). extension Vector2D { static func == (left: Vector2D, right: Vector2D) -> Bool { return (left.x == right.x) && (left.y == right.y) } static func != (left: Vector2D, right: Vector2D) -> Bool { return !(left == right) } } let twoThree = Vector2D(x: 2.0, y: 3.0) let anotherTwoThree = Vector2D(x: 2.0, y: 3.0) if twoThree == anotherTwoThree { print("These two vectors are equivilent.") } // Custom Operators // Custom operators can be defined only with the characters / = - + * % < > ! & | ^ . ~ // +++ prefix doubling incrementer prefix operator +++ extension Vector2D { static prefix func +++ (vector: inout Vector2D) -> Vector2D { vector += vector return vector } } var toBeDoubled = Vector2D(x: 1.0, y: 4.0) let afterDoubling = +++toBeDoubled // Precedence and Associativity for Custom Infix Operators infix operator +-: AdditionPrecedence extension Vector2D { static func +- (left: Vector2D, right: Vector2D) -> Vector2D { return Vector2D(x: left.x + right.x, y: left.y - right.y) } } let firstVector = Vector2D(x: 1.0, y: 2.0) let secondVector = Vector2D(x: 3.0, y: 4.0) let plusMinusVector = firstVector +- secondVector ================================================ FILE: Swift-Playgrounds/The Swift Programming Language/LanguageGuide/25-AdvancedOperators.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/AdoptingCocoaDesignPatterns.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/AdoptingCocoaDesignPatterns.playground/section-1.swift ================================================ // Adopting Cocoa Design Patterns import Cocoa // Delegation /* if let fullScreenSize = myDelegate?.window?(myWindow, willUseFullScreenContentSize: mySize) { println(NSStringFromSize(fullScreenSize)) } */ // 1. Check that myDelegate is not nil. // 2. Check that myDelegate implements the method window:willUseFullScreenContentSize:. // 3. If 1 and 2 hold true, invoke the method and assign the result of the method to the value named fullScreenSize. // 4. Print the return value of the method. // In a pure Swift app, type the delegate property as an optional NSWindowDelegate object and assign it an initial value of nil. class MyDelegate: NSObject, NSWindowDelegate { func window(_ window: NSWindow, willUseFullScreenContentSize proposedSize: NSSize) -> NSSize { return proposedSize } } let myWindow = NSWindow() myWindow.delegate = MyDelegate() //if let fullScreenSize = myWindow.delegate?.window(myWindow, willUseFullScreenContentSize: NSSize()) { // print(NSStringFromSize(fullScreenSize)) //} // Lazy Initialization // Error Reporting // Error reporting in Swift follows the same pattern it does in Objective-C. // In the simplest case, you return a Bool value from the function to indicate whether or not it succeeded. // When you need to report the reason for the error, you can add to the function an NSError out parameter of type NSErrorPointer. This type is roughly equivalent to Objective-C’s NSError **. You can use the prefix & operator to pass in a reference to an optional NSError type as an NSErrorPointer object, as shown in the code listing below. /* var writeError: NSError? let written = myString.writeToFile(path, atomically: false, encoding: NSUTF8StringEncoding, error: &writeError) if !written { if let error = writeError { println("write failure: \(error.localizedDescription)") } } */ // Target-Action // Basically the same as in Objective-C // Introspection // In ObjC you use isKindOfClass: and conformsToProtocol: // In Swift you use the is operator and the as? operator to downcast /*if errorPointer is NSButton { println("\(typeName) is a string") } else { println("typeName is not a string") } if let button = errorPointer as? NSErrorPointer { } */ // Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a class. /* if let dataSource = object as? UITableViewDataSource { // object conforms to UITableViewDataSource and is bound to dataSource } else { // object not conform to UITableViewDataSource } */ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/BasicSetup.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/BasicSetup.playground/section-1.swift ================================================ // Basic Setup // Swift is designed to provide seamless compatibility with Cocoa and Objective-C. /* This guide covers three important aspects of the compatability of Objective-C and Swift - Interoperability, lets you interface between Swift and Objective-C code. - Mix and Match, allows you to create mixed language apps - Migration, from objective-C code to Swift */ // Understanding the Swift Import Process // Any Objective-C framework (or C library) that’s accessible as a module can be imported directly into Swift. import Foundation // The import Process // - Objective-C framworks vend APIs in header files. // - In Swift those header files rae compiled down to Objective-C modules ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/BasicSetup.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/InteractingWithC-APIs.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/InteractingWithC-APIs.playground/section-1.swift ================================================ // Interacting with C APIs import Foundation // Primitive Types // Swift provides equivalents of C primitive integer types—for example, char, int, float, and double. // However, there is no implicit conversion between these types and core Swift integer types, such as Int. Therefore, use these types if your code specifically requires them, but use Int wherever possible otherwise. /* C Type Swift Type bool CBool char, signed char CChar unsigned char CUnsignedChar short CShort unsigned short CUnsignedShort int CInt unsigned int CUnsignedInt long CLong unsigned long CUnsignedLong long long CLongLong unsigned long long CUnsignedLongLong wchar_t CWideChar char16_t CChar16 char32_t CChar32 float CFloat double CDouble */ // Enumerations // Swift imports as a Swift enumeration any C-style enumeration marked with the NS_ENUM macro. /* Objective-C typedef NS_ENUM(NSInteger, UITableViewCellStyle) { UITableViewCellStyleDefault, UITableViewCellStyleValue1, UITableViewCellStyleValue2, UITableViewCellStyleSubtitle } */ enum UITableViewCellStyle: Int { case Default case Value1 case Value2 case Subtitle } // Swift also imports options marked with the NS_OPTIONS macro. Whereas options behave similarly to imported enumerations, options can also support some bitwise operations, such as &, |, and ~. // Pointers /* For Arguments C Syntax Swift Syntax ------------------ ----------------------- const void * CConstVoidPointer void * CMutableVoidPointer const Type * CConstPointer Type * CMutablePointer */ /* For return types, variables, and argument types more than one pointer level deep C Syntax Swift Syntax ------------------ ----------------------- void * COpaquePointer Type * UnsafePointer */ /* For Class Types C Syntax Swift Syntax ------------------ ----------------------- Type * const * CConstPointer Type * __strong * CMutablePointer Type ** AutoreleasingUnsafePointer */ // C Mutable Pointers // When a function is declared as taking a CMutablePointer argument, it can accept any of the following // - nil, which is passed as a null pointer // - A CMutablePointer value // - An in-out expression whose operand is a stored lvalue of type Type, which is passed as the address of the lvalue // - An in-out Type[] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call func takesAMutablePointer(x: UnsafePointer) { // Does something } var x: Float = 0.0 var p: UnsafePointer = nil var a: [Float] = [1.0, 2.0, 3.0] takesAMutablePointer(nil) takesAMutablePointer(p) takesAMutablePointer(&x) takesAMutablePointer(&a) /* func takesAMutablePointer(x: UnsafePointer) { } var y: Int = 0 var p: UnsafePointer = nil var q: UnsafePointer = nil var b: [Int] = [1, 2, 3] */ // C Const Pointers // CConstPointer argument, it can accept any of the following: // - nil, which is passed as a null pointer // - A CMutablePointer, CMutableVoidPointer, CConstPointer, CConstVoidPointer, or AutoreleasingUnsafePointer value, which is converted to CConstPointer if necessary // - An in-out expression whose operand is an lvalue of type Type, which is passed as the address of the lvalue // - A Type[] value, which is passed as a pointer to the start of the array, and lifetime-extended for the duration of the call func takesAMutableVoidPointer(x:UnsafeMutablePointer) { } var x2: Float = 0.0, y2: Int = 0 var p2: UnsafeMutablePointer = nil, q2: UnsafeMutablePointer = nil var a2: [Float] = [1.0, 2.0, 3.0], b2: [Int] = [1,2,3] takesAMutableVoidPointer(nil) takesAMutableVoidPointer(p2) takesAMutableVoidPointer(p2) takesAMutableVoidPointer(&x2) takesAMutableVoidPointer(&y2) takesAMutableVoidPointer(&a2) takesAMutableVoidPointer(&b2) // AutoreleasingUnsafePointer // AutoreleasingUnsafePointer, it can accept any of the following: // - nil, which is passed as a null pointer // - An AutoreleasingUnsafePointer value // - An in-out expression, whose operand is primitive-copied to a temporary nonowning buffer. The address of that buffer is passed to the callee, and on return, the value in the buffer is loaded, retained, and reassigned into the operand. func takesAnAutoreleasingPointer(x: AutoreleasingUnsafeMutablePointer) { /* ... */ } var z: NSDate? = nil var r: AutoreleasingUnsafeMutablePointer = nil takesAnAutoreleasingPointer(nil) takesAnAutoreleasingPointer(r) takesAnAutoreleasingPointer(&z) // Global Constants // Global constants defined in C and Objective-C source files are automatically imported by the Swift compiler as Swift global constants. // Preprocessor Directives // The Swift compiler does not include a preprocessor. Instead, it takes advantage of compile-time attributes, build configurations, and language features to accomplish the same functionality. For this reason, preprocessor directives are not imported in Swift. // #define FADE_ANIMATION_DURATION 0.35 let FADE_ANIMATION_DURATION = 0.35 // the compiler automatically imports simple macros defined in C and Objective-C source // Complex Macros are not transferred across. // Build Configurations // Swift code can be conditionally compiled based on the evaluation of Build Configurations. // Build configurations include the literals true and false, command line flags and the platform testing functions listed below. // You can specify command line flags using -D <#flag#>. /* Function Valid Arguments ------------------ ----------------------- os() OSX, iOS arch() x86_64, arm, arm64, i386 */ /* #if <#build configuration#> && !<#build configuration#> <#statements#> #elseif <#build configuration#> <#statements#> #else <#statements#> #endif */ // Conditional compilation statements in Swift must completely surround blocks of code that are self-contained and syntactically valid. ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/InteractingWithC-APIs.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/InteractingWithObjective-C-APIs.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/InteractingWithObjective-C-APIs.playground/section-1.swift ================================================ //: # Interacting with Objective-C APIs import UIKit //import CoreGraphics //import Foundation //: ## Initialization // UITableView *myTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped]; let myTableView: UITableView = UITableView(frame: CGRect.zero, style: .grouped) let myTextField = UITextField(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 40.0)) // Objective-C Factory Methods // UIColor *color = [UIColor colorWithRed: 0.5 green:0.0 blue:0.5 alpha:1.0] let color = UIColor(red: 0.5, green: 0.0, blue: 0.5, alpha: 1.0) //: ## Failable Initialization if let image = UIImage(contentsOfFile: "MyImage.png") { print(image) } else { print("UIImage initialization failed") } //: ## Accessing Properties myTextField.textColor = UIColor.darkGray myTextField.text = "Hello world" //: In Objective-C, a method that returns a value and takes no arguments can be treated as an implicit getter—and be called using the same syntax as a getter for a property. This is not the case in Swift. In Swift, only properties that are written using the @property syntax in Objective-C are imported as properties. //: ## Working with Methods //: When Objective-C methods come over to Swift, //: - the first part of an Objective-C selector becomes the base method name and appears outside the parentheses. //: - The first argument appears immediately inside the parentheses, without a name. //: - The rest of the selector pieces correspond to argument names and go inside the parentheses. //: - All selector pieces are required at the call site. let mySubview = UIView() // [myTableView insertSubview:mySubview atIndex:2]; myTableView.insertSubview(mySubview, at: 2) myTableView.layoutIfNeeded() // Parenthesis still required despite lack of arguments //: ## id Compatibility //: AnyObject is a protocol type. //: The AnyObject protocol allows you to write type-safe Swift code while maintaining the flexibility of an untyped object. Because of the additional safety provided by the AnyObject protocol, Swift imports id as AnyObject. var x: Any = "hello" as String x as? String x as? NSString x = "goodbye" as NSString x as? String x as? NSString // Downcasting Any let userDefaults = UserDefaults.standard let lastRefreshDate = userDefaults.object(forKey: "LastRefreshDate") // lastRefreshDate is of type Any? if let date = lastRefreshDate as? Date { print("\(date.timeIntervalSinceReferenceDate)") } // If you are cetain of the type of the object, you can use the forced downcast operator // let myDate = lastRefreshDate as! Date // let timeInterval = myDate.timeIntervalSinceReferenceDate // Dynamic Method Lookup var myObject: AnyObject = UITableViewCell() myObject = NSDate() let futureDate = myObject.addingTimeInterval(10) let timeSinceNow = myObject.timeIntervalSinceNow // Unrecognized Selectors and Optional Chaining // myObject.character(at: 5) // crash, myObject doesn't respond to that method let myCount = myObject.count // Int? type and nil value let myChar = myObject.character?(at: 5) // unichar? type and nil value if let fifthCharacter = myObject.character?(at: 5) { print("Found \(fifthCharacter) at index 5") } //: ## Nullability and Optionals //: Swift makes all classes in argument types and return types optional in imported Objective-C APIs. //: Swift imports object types as implicitly unwrapped optionals. var nulableProperty: Any? var nonNullProperty: Any var unannotatedProperty: Any! func returnsNonNullValue() -> Any { return false } func takesNonNullParameter(value: Any) {} func returnsNullableValue() -> Any? { return nil } func takesNullableParameter(value: Any?) {} func returnsUnannotatedValue() -> Any! { return false } func takesUnannotatedParameter(value: Any!) {} // Extensions extension UIBezierPath { convenience init(triangleSideLength: CGFloat, origin: CGPoint) { self.init() let squareRoot = CGFloat(sqrt(3.0)) let altitude = (squareRoot * triangleSideLength) / 2 move(to: origin) addLine(to: CGPoint(x: origin.x + triangleSideLength, y: origin.x)) addLine(to: CGPoint(x: origin.x + triangleSideLength / 2, y: origin.y + altitude)) close() } } // You can use extensions to add properties (including class and static properties). However, these properties must be computed; extensions can’t add stored properties to classes, structures, or enumerations. extension CGRect { var area: CGFloat { return width * height } } let rect = CGRect(x: 0.0, y: 0.0, width: 10.0, height: 50.0) let area = rect.area // Closures // Objective-C blocks are automatically imported as Swift closures. // void (^completionBlock)(NSData *, NSError *) = ^(NSData *data, NSError *error) { /* ... */ } let completionBlock: (Data) -> Void = { data in /* ... */ } // Avoiding String Reference Cycles When Capturing self /* self.closure = { [unowned self] in self.doSomething() } */ // Object Comparison // Equality (==), compares the contents of the objects. // Identity (===), determines whether or not the constants or variables refer to the same object instance. // Swift invokes the isEqual: method defined on the NSObject class. The NSObject class only performs an identity comparison, so you should implement your own isEqual: method in classes that derive from the NSObject class. // // Swift Type Compatibility // The @objc attribute makes your Swift API available in Objective-C and the Objective-C runtime. /* class Jukebox: NSObject { var library: Set var nowPlaying: String? var isCurrentlyPlaying: Bool { return nowPlaying != nil } static var favoritesPlaylist: [String] { // return an array of song names } init(songs: String...) { self.library = Set(songs) } func playSong(named name: String) throws { // play song or throw and error if unavailable } } */ // Configuring Swift Interfaces in Objective-C @objc(Color) enum Цвет: Int { @objc(Red) case Красный @objc(Black) case Черный } @objc(Squirrel) class Белка: NSObject { @objc(color) var цвет: Цвет = .Красный @objc(initWithName:) init(имя: String) { // ... } @objc(hideNuts:inTree:) func прячьОрехи(количество: Int, вДереве дерево: Цвет) { // Error // ... } } // Requiring Dynamic Dispatch // Selectors // An Objective-C selector is a type that refers to the name of an Objective-C method. In Swift, Objective-C selectors are represented by the Selector structure. // In Swift string literals can be automatically converted to selectors class MyViewController: UIViewController { let myButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50)) override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) { super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil) let action = #selector(MyViewController.tappedButton) myButton.addTarget(self, action: action, for: .touchUpInside) } func tappedButton(sender: UIButton!) { print("tapped button") } required init?(coder: NSCoder) { super.init(coder: coder) } } // Unsafe Invocation of Objective-C Methods let string: NSString = "Hello, Cocoa!" let selector = #selector(NSString.lowercased(with:)) let locale = Locale.current if let result = string.perform(selector, with: locale) { print(result.takeUnretainedValue()) } let array: NSArray = ["delta", "alpha", "zulu"] let anotherSelector = #selector(getter: NSDictionary.allKeys) // array.perform(selector) // Raises an exception because NSArray does not respond to this selector // Keys and Key Paths class Person: NSObject { var name: String var friends: [Person] = [] var bestFriend: Person? = nil init(name: String) { self.name = name } } let gabrielle = Person(name: "Gabrielle") let jim = Person(name: "Jim") let yuanyuan = Person(name: "Yuanyuan") gabrielle.friends = [jim, yuanyuan] gabrielle.bestFriend = yuanyuan #keyPath(Person.name) gabrielle.value(forKey: #keyPath(Person.name)) #keyPath(Person.bestFriend.name) gabrielle.value(forKeyPath: #keyPath(Person.bestFriend.name)) #keyPath(Person.friends.name) gabrielle.value(forKeyPath: #keyPath(Person.friends.name)) let personNameKeyPath = #keyPath(Person.name) yuanyuan.value(forKeyPath: personNameKeyPath) ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/Mix&Match.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/Mix&Match.playground/section-1.swift ================================================ // Mix and Match ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/Mix&Match.playground/timeline.xctimeline ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/WorkingWithCocoaDataTypes.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/Using Swift With Cocoa And Objective-C/WorkingWithCocoaDataTypes.playground/section-1.swift ================================================ // Working with Cocoa Frameworks // Data types that are convertible or can be used interchangeably are referred to as bridged data types. import UIKit // Strings // Swift automatically bridges between the String type and the NSString class. // To enable string bridging, just import Foundation. import Foundation let string: String = "abc" let bridgedString: NSString = string as NSString let stringLiteral: NSString = "123" if let integerValue = Int(stringLiteral as String) { print("\(stringLiteral) is the integer \(integerValue)") } // Numbers // Swift automatically bridges from Int, UInt, Float, Double, Bool to NSNumber let number = 42 let bridgedNumber: NSNumber = number as NSNumber let integerLiteral: NSNumber = 5 let floatLiteral: NSNumber = 3.14159 let booleanLiteral: NSNumber = true // Arrays // Swift automatically bridges from NSArray to the native Array structure. The bridged class will be of type AnyObject[]. You can downcast the AnyObject[] to a more specific type. This will return an optional type though as it is not possible to know that all of the elements of the array can be downcast to the specified type until runtime. let schoolSupplies: NSArray = ["Pencil", "Eraser", "Notebook"] // Sets let amenities: NSSet = ["Sauna", "Steam Room", "Jacuzzi"] // Dictionaries let medalRankings: NSDictionary = ["Gold": "1st Place", "Silver": "2nd Place", "Bronze": "3rd Place"] // Core Foundation // Core Foundation types are automatically imported as full-fledged Swift classes. Wherever memory management annotations have been provided, Swift automatically manages the memory of Core Foundation objects, including Core Foundation objects that you instantiate yourself. // Remapped Types // When Swift imports Core Foundation types, the compiler remaps the names of these types. The compiler removes Ref from the end of each type name because all Swift classes are reference types, therefore the suffix is redundant. // The Core Foundation CFTypeRef type completely remaps to the AnyObject type. Wherever you would use CFTypeRef, you should now use AnyObject in your code. // Memory Managed Objects // Core Foundation objects returned from annotated APIs are automatically memory managed in Swift—you do not need to invoke the CFRetain, CFRelease, or CFAutorelease functions yourself. // Unmanaged Objects // When Swift imports APIs that have not been annotated, the compiler cannot automatically memory manage the returned Core Foundation objects. Swift wraps these returned Core Foundation objects in an Unmanaged structure. All indirectly returned Core Foundation objects are unmanaged as well. For example, here’s an unannotated C function: /* Objective-C CFStringRef StringByAddingTwoStrings(CFStringRef string1, CFStringRef string2) Swift func StringByAddingTwoStrings(CFString!, CFString!) -> Unmanaged! */ // When you receive an unmanaged object from an unannotated API, you should immediately convert it to a memory managed object before you work with it. Use takeUnretainedValue() or takeRetainedValue() /* let memoryManagedResult = StringByAddingTwoStrings(str1, str2).takeUnretainedValue() */ // Unified Logging // The unified logging system provides an API for capturing messaging across all levels of the system, and is a replacement for the NSLog function in the Foundation framework. /* import os.log os_log("This is a log message.") let fileSize = 1234567890 os_log("Finished downloading file. Size: %{iec-bytes}d", fileSize) os_log("This is additional info that may be helpful for troubleshooting.", type: .info) let customLog = OSLog(subsystem: "com.your_company.your_subsystem_name.plist", category: "your_category_name") os_log("This is info that may be helpful during development or debugging.", log: customLog, type: .debug) */ ================================================ FILE: Swift-Playgrounds/WWDC/2014/AdvancedSwift.playground/Contents.swift ================================================ // WWDC 2014 - Advanced Swift class Thing { init(_ location: Thing?, _ name: String, _ longDescription: String) { self.location = location self.name = name self.longDescription = longDescription } weak var location: Thing? var name: String var longDescription: String } let westOfHouse = Thing(nil, "house", "West of House") let westWallOfHouse = Thing(westOfHouse, "wall", "The Plaster has crumbled away, leaving the wood beneath to rot.") let pathWestOfHouse = Thing(westOfHouse, "path", "An overgrown path leads south around the corner of the house.") protocol Pullable { func pull() } class Boards: Thing, Pullable { func pull() { if location === westWallOfHouse { print("They come off with little effort.") location = westOfHouse } else { print("Think of the splinters!") } } } let boards = Boards(westWallOfHouse, "boards", "They've been nailed directly to the wall.") /* func performPull(object: Thing) { if let pullableObject = object as Pullable { pullableObject.pull() } else { println("You aren't sure how to print a \(object.name).") } } */ extension Thing: CustomStringConvertible { var description: String { return name } } extension Thing { var nameWithArticle: String { return "a " + name } } var object = Thing(westOfHouse, "wall", "The Plaster has crumbled away, leaving the wood beneath to rot.") // Printable doesn't work in a playground yet (Beta 3) print("You aren't sure how to pull \(object)") //println("You aren't sure how to pull \(object.description)") //println("You aren't sure how to pull \(an ~ object)") /* // Special Protocols // LogicValue if logicValue { // Printable "\(printable)" // Sequence for x in sequence // IntegerLiteralConvertible 65536 // Float LIteralConvertible 1.0 // StringLiteralConvertible "abc" // ArrayLiteralConvertible [ a, b, c ] // DictionaryLiteralConvertible [ a: x, b: y ] protocol Printable { var description: String { get } } */ /* // Overloading an operator operator infix ~ {} // Define the operator you want to use // infix, postfix and prefix are options func ~ (decorator: (Thing) -> String, object: Thing -> String { return decorator(object) }) func an(object: Thing) -> String { return object.nameWithArticle } let mud = Thing(westOfHouse, "mud", "I don't know") println("You aren't sure how to pull \(an ~ mud).") */ // Defining a Place enum Direction { case North, South, East, West } /* class Place: Thing { //init(_ name: String, _ longDescription: String) { // super.init(<#Thing?#>, <#String#>, <#String#>) //} //var exits: Dictionary = */ ================================================ FILE: Swift-Playgrounds/WWDC/2014/AdvancedSwift.playground/contents.xcplayground ================================================ ================================================ FILE: Swift-Playgrounds/main.swift ================================================ // // main.swift // Swift-Playgrounds // // Created by Daniel Pink on 5/06/2014. // Copyright (c) 2014 Electronic Innovations. All rights reserved. // import Cocoa NSApplicationMain(C_ARGC, C_ARGV) ================================================ FILE: Swift-Playgrounds.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ E66B1CC01E4C183C00B6593E /* README.md in Sources */ = {isa = PBXBuildFile; fileRef = E66B1CBF1E4C183C00B6593E /* README.md */; }; E6C330A81E4C00CD0000AA37 /* icon_56811.png in Resources */ = {isa = PBXBuildFile; fileRef = E6C330A61E4C00CD0000AA37 /* icon_56811.png */; }; E6E1BED819401B3600DA4D53 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = E6E1BED719401B3600DA4D53 /* main.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ E6E1BEE519401B3600DA4D53 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = E6E1BECA19401B3600DA4D53 /* Project object */; proxyType = 1; remoteGlobalIDString = E6E1BED119401B3600DA4D53; remoteInfo = "Swift-Playgrounds"; }; /* End PBXContainerItemProxy section */ /* Begin PBXFileReference section */ E61C4B621E4BFC0200E4E565 /* ASwiftTour.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = ASwiftTour.playground; sourceTree = ""; }; E61C4B641E4BFC0200E4E565 /* 01-TheBasics.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "01-TheBasics.playground"; sourceTree = ""; }; E61C4B651E4BFC0200E4E565 /* 02-BasicOperators.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "02-BasicOperators.playground"; sourceTree = ""; }; E61C4B661E4BFC0200E4E565 /* 03-StringsAndCharacters.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "03-StringsAndCharacters.playground"; sourceTree = ""; }; E61C4B671E4BFC0200E4E565 /* 04-CollectionTypes.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "04-CollectionTypes.playground"; sourceTree = ""; }; E61C4B681E4BFC0200E4E565 /* 05-ControlFlow.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "05-ControlFlow.playground"; sourceTree = ""; }; E61C4B691E4BFC0200E4E565 /* 06-Functions.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "06-Functions.playground"; sourceTree = ""; }; E61C4B6A1E4BFC0200E4E565 /* 07-Closures.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "07-Closures.playground"; sourceTree = ""; }; E61C4B6B1E4BFC0200E4E565 /* 08-Enumerations.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "08-Enumerations.playground"; sourceTree = ""; }; E61C4B6C1E4BFC0200E4E565 /* 09-ClassesAndStructures.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "09-ClassesAndStructures.playground"; sourceTree = ""; }; E61C4B6D1E4BFC0200E4E565 /* 10-Properties.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "10-Properties.playground"; sourceTree = ""; }; E61C4B6E1E4BFC0200E4E565 /* 11-Methods.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "11-Methods.playground"; sourceTree = ""; }; E61C4B6F1E4BFC0200E4E565 /* 12-Subscripts.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "12-Subscripts.playground"; sourceTree = ""; }; E61C4B701E4BFC0200E4E565 /* 13-Inheritance.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "13-Inheritance.playground"; sourceTree = ""; }; E61C4B711E4BFC0200E4E565 /* 14-Initialization.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "14-Initialization.playground"; sourceTree = ""; }; E61C4B721E4BFC0200E4E565 /* 15-Deinitialization.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "15-Deinitialization.playground"; sourceTree = ""; }; E61C4B731E4BFC0200E4E565 /* 16-AutomaticReferenceCounting.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "16-AutomaticReferenceCounting.playground"; sourceTree = ""; }; E61C4B741E4BFC0200E4E565 /* 17-OptionalChaining.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "17-OptionalChaining.playground"; sourceTree = ""; }; E61C4B751E4BFC0200E4E565 /* 18-ErrorHandling.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "18-ErrorHandling.playground"; sourceTree = ""; }; E61C4B761E4BFC0200E4E565 /* 19-TypeCasting.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "19-TypeCasting.playground"; sourceTree = ""; }; E61C4B771E4BFC0200E4E565 /* 20-NestedTypes.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "20-NestedTypes.playground"; sourceTree = ""; }; E61C4B781E4BFC0200E4E565 /* 21-Extensions.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "21-Extensions.playground"; sourceTree = ""; }; E61C4B791E4BFC0200E4E565 /* 22-Protocols.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "22-Protocols.playground"; sourceTree = ""; }; E61C4B7A1E4BFC0300E4E565 /* 23-Generics.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "23-Generics.playground"; sourceTree = ""; }; E61C4B7B1E4BFC0300E4E565 /* 24-AccessControl.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "24-AccessControl.playground"; sourceTree = ""; }; E61C4B7C1E4BFC0300E4E565 /* 25-AdvancedOperators.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "25-AdvancedOperators.playground"; sourceTree = ""; }; E66B1CBF1E4C183C00B6593E /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; E6C3307F1E4BFCCF0000AA37 /* Swift-Playgrounds.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Swift-Playgrounds.app"; sourceTree = BUILT_PRODUCTS_DIR; }; E6C330801E4BFCCF0000AA37 /* Swift-PlaygroundsTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "Swift-PlaygroundsTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; E6C330831E4C008E0000AA37 /* AdoptingCocoaDesignPatterns.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = AdoptingCocoaDesignPatterns.playground; sourceTree = ""; }; E6C330841E4C008E0000AA37 /* BasicSetup.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = BasicSetup.playground; sourceTree = ""; }; E6C330851E4C008E0000AA37 /* InteractingWithC-APIs.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "InteractingWithC-APIs.playground"; sourceTree = ""; }; E6C330861E4C008E0000AA37 /* InteractingWithObjective-C-APIs.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "InteractingWithObjective-C-APIs.playground"; sourceTree = ""; }; E6C330871E4C008E0000AA37 /* Mix&Match.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "Mix&Match.playground"; sourceTree = ""; }; E6C330881E4C008E0000AA37 /* WorkingWithCocoaDataTypes.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = WorkingWithCocoaDataTypes.playground; sourceTree = ""; }; E6C3308A1E4C00A50000AA37 /* Array.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Array.playground; sourceTree = ""; }; E6C3308B1E4C00A50000AA37 /* Dictionary.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Dictionary.playground; sourceTree = ""; }; E6C3308C1E4C00A50000AA37 /* FreeFunctions.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = FreeFunctions.playground; sourceTree = ""; }; E6C3308D1E4C00A50000AA37 /* NumericTypes.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = NumericTypes.playground; sourceTree = ""; }; E6C3308E1E4C00A50000AA37 /* Protocols.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Protocols.playground; sourceTree = ""; }; E6C3308F1E4C00A50000AA37 /* String.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = String.playground; sourceTree = ""; }; E6C330901E4C00A50000AA37 /* Undocumented.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = Undocumented.playground; sourceTree = ""; }; E6C330921E4C00CD0000AA37 /* 2014-08-11-SwiftOperators.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-11-SwiftOperators.playground"; sourceTree = ""; }; E6C330931E4C00CD0000AA37 /* Cheryls-Birthday-Alternative-1.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "Cheryls-Birthday-Alternative-1.playground"; sourceTree = ""; }; E6C330941E4C00CD0000AA37 /* Cheryls-Birthday.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "Cheryls-Birthday.playground"; sourceTree = ""; }; E6C330951E4C00CD0000AA37 /* WritingSwiftClassesWithObjectiveCBehaviour.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = WritingSwiftClassesWithObjectiveCBehaviour.playground; sourceTree = ""; }; E6C330971E4C00CD0000AA37 /* 2014-08-08-LockingInSwift.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-08-LockingInSwift.playground"; sourceTree = ""; }; E6C330991E4C00CD0000AA37 /* 2014-08-18-SwiftLiteralConvertibles.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-18-SwiftLiteralConvertibles.playground"; sourceTree = ""; }; E6C3309B1E4C00CD0000AA37 /* 2014-07-23-AccessControl.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-07-23-AccessControl.playground"; sourceTree = ""; }; E6C3309C1E4C00CD0000AA37 /* 2014-07-28-InteractingWithCPointers.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-07-28-InteractingWithCPointers.playground"; sourceTree = ""; }; E6C3309D1E4C00CD0000AA37 /* 2014-08-05-Boolean.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-05-Boolean.playground"; sourceTree = ""; }; E6C3309E1E4C00CD0000AA37 /* 2014-08-15-ValueAndReferenceTypes.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-15-ValueAndReferenceTypes.playground"; sourceTree = ""; }; E6C3309F1E4C00CD0000AA37 /* 2014-08-27-OptionalCaseStudy-valuesForKeys.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = "2014-08-27-OptionalCaseStudy-valuesForKeys.playground"; sourceTree = ""; }; E6C330A21E4C00CD0000AA37 /* AdvancedSwift.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = AdvancedSwift.playground; sourceTree = ""; }; E6C330A51E4C00CD0000AA37 /* GameDevUniversity.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = GameDevUniversity.playground; sourceTree = ""; }; E6C330A61E4C00CD0000AA37 /* icon_56811.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = icon_56811.png; sourceTree = ""; }; E6C330A71E4C00CD0000AA37 /* SpriteKitTestbed.playground */ = {isa = PBXFileReference; lastKnownFileType = file.playground; path = SpriteKitTestbed.playground; sourceTree = ""; }; E6E1BED619401B3600DA4D53 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; E6E1BED719401B3600DA4D53 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ E6E1BECF19401B3600DA4D53 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; E6E1BEE119401B3600DA4D53 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ E61C4B611E4BFC0200E4E565 /* The Swift Programming Language */ = { isa = PBXGroup; children = ( E61C4B621E4BFC0200E4E565 /* ASwiftTour.playground */, E61C4B631E4BFC0200E4E565 /* LanguageGuide */, ); path = "The Swift Programming Language"; sourceTree = ""; }; E61C4B631E4BFC0200E4E565 /* LanguageGuide */ = { isa = PBXGroup; children = ( E61C4B641E4BFC0200E4E565 /* 01-TheBasics.playground */, E61C4B651E4BFC0200E4E565 /* 02-BasicOperators.playground */, E61C4B661E4BFC0200E4E565 /* 03-StringsAndCharacters.playground */, E61C4B671E4BFC0200E4E565 /* 04-CollectionTypes.playground */, E61C4B681E4BFC0200E4E565 /* 05-ControlFlow.playground */, E61C4B691E4BFC0200E4E565 /* 06-Functions.playground */, E61C4B6A1E4BFC0200E4E565 /* 07-Closures.playground */, E61C4B6B1E4BFC0200E4E565 /* 08-Enumerations.playground */, E61C4B6C1E4BFC0200E4E565 /* 09-ClassesAndStructures.playground */, E61C4B6D1E4BFC0200E4E565 /* 10-Properties.playground */, E61C4B6E1E4BFC0200E4E565 /* 11-Methods.playground */, E61C4B6F1E4BFC0200E4E565 /* 12-Subscripts.playground */, E61C4B701E4BFC0200E4E565 /* 13-Inheritance.playground */, E61C4B711E4BFC0200E4E565 /* 14-Initialization.playground */, E61C4B721E4BFC0200E4E565 /* 15-Deinitialization.playground */, E61C4B731E4BFC0200E4E565 /* 16-AutomaticReferenceCounting.playground */, E61C4B741E4BFC0200E4E565 /* 17-OptionalChaining.playground */, E61C4B751E4BFC0200E4E565 /* 18-ErrorHandling.playground */, E61C4B761E4BFC0200E4E565 /* 19-TypeCasting.playground */, E61C4B771E4BFC0200E4E565 /* 20-NestedTypes.playground */, E61C4B781E4BFC0200E4E565 /* 21-Extensions.playground */, E61C4B791E4BFC0200E4E565 /* 22-Protocols.playground */, E61C4B7A1E4BFC0300E4E565 /* 23-Generics.playground */, E61C4B7B1E4BFC0300E4E565 /* 24-AccessControl.playground */, E61C4B7C1E4BFC0300E4E565 /* 25-AdvancedOperators.playground */, ); path = LanguageGuide; sourceTree = ""; }; E6C330821E4C008E0000AA37 /* Using Swift With Cocoa And Objective-C */ = { isa = PBXGroup; children = ( E6C330831E4C008E0000AA37 /* AdoptingCocoaDesignPatterns.playground */, E6C330841E4C008E0000AA37 /* BasicSetup.playground */, E6C330851E4C008E0000AA37 /* InteractingWithC-APIs.playground */, E6C330861E4C008E0000AA37 /* InteractingWithObjective-C-APIs.playground */, E6C330871E4C008E0000AA37 /* Mix&Match.playground */, E6C330881E4C008E0000AA37 /* WorkingWithCocoaDataTypes.playground */, ); path = "Using Swift With Cocoa And Objective-C"; sourceTree = ""; }; E6C330891E4C00A50000AA37 /* Swift Stanard Library */ = { isa = PBXGroup; children = ( E6C3308A1E4C00A50000AA37 /* Array.playground */, E6C3308B1E4C00A50000AA37 /* Dictionary.playground */, E6C3308C1E4C00A50000AA37 /* FreeFunctions.playground */, E6C3308D1E4C00A50000AA37 /* NumericTypes.playground */, E6C3308E1E4C00A50000AA37 /* Protocols.playground */, E6C3308F1E4C00A50000AA37 /* String.playground */, E6C330901E4C00A50000AA37 /* Undocumented.playground */, ); path = "Swift Stanard Library"; sourceTree = ""; }; E6C330911E4C00CD0000AA37 /* Others */ = { isa = PBXGroup; children = ( E6C330921E4C00CD0000AA37 /* 2014-08-11-SwiftOperators.playground */, E6C330931E4C00CD0000AA37 /* Cheryls-Birthday-Alternative-1.playground */, E6C330941E4C00CD0000AA37 /* Cheryls-Birthday.playground */, E6C330951E4C00CD0000AA37 /* WritingSwiftClassesWithObjectiveCBehaviour.playground */, ); path = Others; sourceTree = ""; }; E6C330961E4C00CD0000AA37 /* Blogs */ = { isa = PBXGroup; children = ( E6C330971E4C00CD0000AA37 /* 2014-08-08-LockingInSwift.playground */, E6C330981E4C00CD0000AA37 /* NSHipster */, E6C3309A1E4C00CD0000AA37 /* Swift Blog */, ); path = Blogs; sourceTree = ""; }; E6C330981E4C00CD0000AA37 /* NSHipster */ = { isa = PBXGroup; children = ( E6C330991E4C00CD0000AA37 /* 2014-08-18-SwiftLiteralConvertibles.playground */, ); path = NSHipster; sourceTree = ""; }; E6C3309A1E4C00CD0000AA37 /* Swift Blog */ = { isa = PBXGroup; children = ( E6C3309B1E4C00CD0000AA37 /* 2014-07-23-AccessControl.playground */, E6C3309C1E4C00CD0000AA37 /* 2014-07-28-InteractingWithCPointers.playground */, E6C3309D1E4C00CD0000AA37 /* 2014-08-05-Boolean.playground */, E6C3309E1E4C00CD0000AA37 /* 2014-08-15-ValueAndReferenceTypes.playground */, E6C3309F1E4C00CD0000AA37 /* 2014-08-27-OptionalCaseStudy-valuesForKeys.playground */, ); path = "Swift Blog"; sourceTree = ""; }; E6C330A01E4C00CD0000AA37 /* WWDC */ = { isa = PBXGroup; children = ( E6C330A11E4C00CD0000AA37 /* 2014 */, ); path = WWDC; sourceTree = ""; }; E6C330A11E4C00CD0000AA37 /* 2014 */ = { isa = PBXGroup; children = ( E6C330A21E4C00CD0000AA37 /* AdvancedSwift.playground */, ); path = 2014; sourceTree = ""; }; E6C330A31E4C00CD0000AA37 /* Specific Technologies */ = { isa = PBXGroup; children = ( E6C330A41E4C00CD0000AA37 /* SpriteKit */, ); path = "Specific Technologies"; sourceTree = ""; }; E6C330A41E4C00CD0000AA37 /* SpriteKit */ = { isa = PBXGroup; children = ( E6C330A51E4C00CD0000AA37 /* GameDevUniversity.playground */, E6C330A61E4C00CD0000AA37 /* icon_56811.png */, E6C330A71E4C00CD0000AA37 /* SpriteKitTestbed.playground */, ); path = SpriteKit; sourceTree = ""; }; E6E1BEC919401B3600DA4D53 = { isa = PBXGroup; children = ( E66B1CBF1E4C183C00B6593E /* README.md */, E6E1BED419401B3600DA4D53 /* Swift-Playgrounds */, E6C3307F1E4BFCCF0000AA37 /* Swift-Playgrounds.app */, E6C330801E4BFCCF0000AA37 /* Swift-PlaygroundsTests.xctest */, ); sourceTree = ""; }; E6E1BED419401B3600DA4D53 /* Swift-Playgrounds */ = { isa = PBXGroup; children = ( E61C4B611E4BFC0200E4E565 /* The Swift Programming Language */, E6C330821E4C008E0000AA37 /* Using Swift With Cocoa And Objective-C */, E6C330891E4C00A50000AA37 /* Swift Stanard Library */, E6C330911E4C00CD0000AA37 /* Others */, E6C330961E4C00CD0000AA37 /* Blogs */, E6C330A01E4C00CD0000AA37 /* WWDC */, E6C330A31E4C00CD0000AA37 /* Specific Technologies */, E6E1BED519401B3600DA4D53 /* Supporting Files */, ); path = "Swift-Playgrounds"; sourceTree = ""; }; E6E1BED519401B3600DA4D53 /* Supporting Files */ = { isa = PBXGroup; children = ( E6E1BED619401B3600DA4D53 /* Info.plist */, E6E1BED719401B3600DA4D53 /* main.swift */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ E6E1BED119401B3600DA4D53 /* Swift-Playgrounds */ = { isa = PBXNativeTarget; buildConfigurationList = E6E1BEEE19401B3600DA4D53 /* Build configuration list for PBXNativeTarget "Swift-Playgrounds" */; buildPhases = ( E6E1BECE19401B3600DA4D53 /* Sources */, E6E1BECF19401B3600DA4D53 /* Frameworks */, E6E1BED019401B3600DA4D53 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = "Swift-Playgrounds"; productName = "Swift-Playgrounds"; productReference = E6C3307F1E4BFCCF0000AA37 /* Swift-Playgrounds.app */; productType = "com.apple.product-type.application"; }; E6E1BEE319401B3600DA4D53 /* Swift-PlaygroundsTests */ = { isa = PBXNativeTarget; buildConfigurationList = E6E1BEF119401B3600DA4D53 /* Build configuration list for PBXNativeTarget "Swift-PlaygroundsTests" */; buildPhases = ( E6E1BEE019401B3600DA4D53 /* Sources */, E6E1BEE119401B3600DA4D53 /* Frameworks */, E6E1BEE219401B3600DA4D53 /* Resources */, ); buildRules = ( ); dependencies = ( E6E1BEE619401B3600DA4D53 /* PBXTargetDependency */, ); name = "Swift-PlaygroundsTests"; productName = "Swift-PlaygroundsTests"; productReference = E6C330801E4BFCCF0000AA37 /* Swift-PlaygroundsTests.xctest */; productType = "com.apple.product-type.bundle.unit-test"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ E6E1BECA19401B3600DA4D53 /* Project object */ = { isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Electronic Innovations"; TargetAttributes = { E6E1BED119401B3600DA4D53 = { CreatedOnToolsVersion = 6.0; LastSwiftMigration = 0820; }; E6E1BEE319401B3600DA4D53 = { CreatedOnToolsVersion = 6.0; LastSwiftMigration = 0820; TestTargetID = E6E1BED119401B3600DA4D53; }; }; }; buildConfigurationList = E6E1BECD19401B3600DA4D53 /* Build configuration list for PBXProject "Swift-Playgrounds" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = E6E1BEC919401B3600DA4D53; productRefGroup = E6E1BEC919401B3600DA4D53; projectDirPath = ""; projectRoot = ""; targets = ( E6E1BED119401B3600DA4D53 /* Swift-Playgrounds */, E6E1BEE319401B3600DA4D53 /* Swift-PlaygroundsTests */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ E6E1BED019401B3600DA4D53 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( E6C330A81E4C00CD0000AA37 /* icon_56811.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; E6E1BEE219401B3600DA4D53 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ E6E1BECE19401B3600DA4D53 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( E66B1CC01E4C183C00B6593E /* README.md in Sources */, E6E1BED819401B3600DA4D53 /* main.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; E6E1BEE019401B3600DA4D53 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ E6E1BEE619401B3600DA4D53 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = E6E1BED119401B3600DA4D53 /* Swift-Playgrounds */; targetProxy = E6E1BEE519401B3600DA4D53 /* PBXContainerItemProxy */; }; /* End PBXTargetDependency section */ /* Begin XCBuildConfiguration section */ E6E1BEEC19401B3600DA4D53 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = macosx; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; name = Debug; }; E6E1BEED19401B3600DA4D53 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CODE_SIGN_IDENTITY = "-"; COPY_PHASE_STRIP = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; GCC_WARN_UNDECLARED_SELECTOR = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; MACOSX_DEPLOYMENT_TARGET = 10.9; METAL_ENABLE_DEBUG_INFO = NO; SDKROOT = macosx; }; name = Release; }; E6E1BEEF19401B3600DA4D53 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "Swift-Playgrounds/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "au.com.electronicinnovations.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Debug; }; E6E1BEF019401B3600DA4D53 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; COMBINE_HIDPI_IMAGES = YES; INFOPLIST_FILE = "Swift-Playgrounds/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "au.com.electronicinnovations.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; name = Release; }; E6E1BEF219401B3600DA4D53 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Swift-Playgrounds.app/Contents/MacOS/Swift-Playgrounds"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); INFOPLIST_FILE = "Swift-PlaygroundsTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; METAL_ENABLE_DEBUG_INFO = YES; PRODUCT_BUNDLE_IDENTIFIER = "au.com.electronicinnovations.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Debug; }; E6E1BEF319401B3600DA4D53 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Swift-Playgrounds.app/Contents/MacOS/Swift-Playgrounds"; COMBINE_HIDPI_IMAGES = YES; FRAMEWORK_SEARCH_PATHS = ( "$(DEVELOPER_FRAMEWORKS_DIR)", "$(inherited)", ); INFOPLIST_FILE = "Swift-PlaygroundsTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks"; METAL_ENABLE_DEBUG_INFO = NO; PRODUCT_BUNDLE_IDENTIFIER = "au.com.electronicinnovations.${PRODUCT_NAME:rfc1034identifier}"; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; TEST_HOST = "$(BUNDLE_LOADER)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ E6E1BECD19401B3600DA4D53 /* Build configuration list for PBXProject "Swift-Playgrounds" */ = { isa = XCConfigurationList; buildConfigurations = ( E6E1BEEC19401B3600DA4D53 /* Debug */, E6E1BEED19401B3600DA4D53 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E6E1BEEE19401B3600DA4D53 /* Build configuration list for PBXNativeTarget "Swift-Playgrounds" */ = { isa = XCConfigurationList; buildConfigurations = ( E6E1BEEF19401B3600DA4D53 /* Debug */, E6E1BEF019401B3600DA4D53 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; E6E1BEF119401B3600DA4D53 /* Build configuration list for PBXNativeTarget "Swift-PlaygroundsTests" */ = { isa = XCConfigurationList; buildConfigurations = ( E6E1BEF219401B3600DA4D53 /* Debug */, E6E1BEF319401B3600DA4D53 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = E6E1BECA19401B3600DA4D53 /* Project object */; } ================================================ FILE: Thoughts-Questions.txt ================================================ Swift Thoughts and Questions - How do you get pretty printing of instances in the playground? - Could you get a pretty printout of something like a 2D matrix? - How does Phase two of object initialization work? - In the Deinitialization Chapter is the Bank object (that only contains Type properties and methods) a hacky way of having a singleton? - The Player deinitialization method doesn't get called in the playground when the playerOne variable is set to nil. In "Using Swift with Cocoa and Objective-C" - let myTextField = UITextField(frame: CGRect(0.0, 0.0, 200.0, 40.0)) is corrected by the playground autocorrecto to let myTextField = UITextField(frame: CGRect(x: 0.0, y: 0.0, width: 200.0, height: 40.0)) - myTextField.editing = false is reported as an error as editing is not allowed to be assigned. - The following doesn't seem to work in a playground let myLength = myObject.length? if let fifthCharacter = myObject.characterAtIndex(5) { println("Found \(fifthCharacter) at index 5") } - let squareRoot = Float(sqrt(3)) gives an "Ambiguous use of sqrt in Beta 3". It doesn't look like you can call sqrt() on an integer. - The following code gives a error in the playground no matter what object and UIButton are. if object is UIButton { // object is of type UIButton } else { // object is not of type UIButton }