From a19efad7fc938c2e505582a3541a3c083d0f85c8 Mon Sep 17 00:00:00 2001 From: Kyle Rokita Date: Fri, 11 Nov 2016 16:12:13 -0800 Subject: Added nil-coalescing operator --- swift.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index b6554dc6..c17510b6 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -104,6 +104,11 @@ if let someOptionalStringConstant = someOptionalString { } } +// The nil-coalescing operator ?? unwraps an optional if it contains a non-nil value, or returns a default value. +var someOptionalString: String? +let someString = someOptionalString ?? "abc" +print(someString) // abc + // Swift has support for storing a value of any type. // For that purposes there is two keywords: `Any` and `AnyObject` // `AnyObject` == `id` from Objective-C -- cgit v1.2.3 From 985d23a52b76593a120adff5381c2df3a80fe298 Mon Sep 17 00:00:00 2001 From: HairyFotr Date: Wed, 23 Aug 2017 10:14:39 +0200 Subject: Fix a bunch of typos --- swift.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index c17510b6..60915d72 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -281,7 +281,7 @@ testGuard() // Variadic Args func setup(numbers: Int...) { - // its an array + // it's an array let _ = numbers[0] let _ = numbers.count } -- cgit v1.2.3 From 62d4b1483b850da0a99c2aa6c2da8b013e308f50 Mon Sep 17 00:00:00 2001 From: Damian Rzeszot Date: Mon, 9 Oct 2017 11:56:50 +0200 Subject: swift | fix style guidelines --- swift.html.markdown | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 60915d72..46388ca5 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -361,14 +361,14 @@ print("Name is \(name)") // Name is Them // The `Error` protocol is used when throwing errors to catch enum MyError: Error { - case BadValue(msg: String) - case ReallyBadValue(msg: String) + case badValue(msg: String) + case reallyBadValue(msg: String) } // functions marked with `throws` must be called using `try` func fakeFetch(value: Int) throws -> String { guard 7 == value else { - throw MyError.ReallyBadValue(msg: "Some really bad value") + throw MyError.reallyBadValue(msg: "Some really bad value") } return "test" @@ -385,7 +385,7 @@ func testTryStuff() { do { // normal try operation that provides error handling via `catch` block try fakeFetch(value: 1) - } catch MyError.BadValue(let msg) { + } catch MyError.badValue(let msg) { print("Error message: \(msg)") } catch { // must be exhaustive -- cgit v1.2.3 From d01e5242e16c522becc1b04f9692d2556f94c4f1 Mon Sep 17 00:00:00 2001 From: Damian Rzeszot Date: Mon, 9 Oct 2017 12:01:15 +0200 Subject: swift | fix style guidelines --- swift.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 46388ca5..577fa559 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -518,20 +518,20 @@ if let circle = myEmptyCircle { // They can contain methods like classes. enum Suit { - case Spades, Hearts, Diamonds, Clubs + case spades, hearts, diamonds, clubs func getIcon() -> String { switch self { - case .Spades: return "♤" - case .Hearts: return "♡" - case .Diamonds: return "♢" - case .Clubs: return "♧" + case .spades: return "♤" + case .hearts: return "♡" + case .diamonds: return "♢" + case .clubs: return "♧" } } } // Enum values allow short hand syntax, no need to type the enum type // when the variable is explicitly declared -var suitValue: Suit = .Hearts +var suitValue: Suit = .hearts // String enums can have direct raw value assignments // or their raw values will be derived from the Enum field -- cgit v1.2.3 From 9a9e52b54bf9bc6ebeefc996452f5944a234557f Mon Sep 17 00:00:00 2001 From: Damian Rzeszot Date: Mon, 9 Oct 2017 12:02:29 +0200 Subject: swift | fix style guidelines --- swift.html.markdown | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 577fa559..a3b33e25 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -536,10 +536,10 @@ var suitValue: Suit = .hearts // String enums can have direct raw value assignments // or their raw values will be derived from the Enum field enum BookName: String { - case John - case Luke = "Luke" + case john + case luke = "Luke" } -print("Name: \(BookName.John.rawValue)") +print("Name: \(BookName.john.rawValue)") // Enum with associated Values enum Furniture { -- cgit v1.2.3 From e8ee66c854b8833fcb0fd76b5e9ace6ae8379397 Mon Sep 17 00:00:00 2001 From: Damian Rzeszot Date: Mon, 9 Oct 2017 12:03:27 +0200 Subject: swift | fix style guidelines --- swift.html.markdown | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index a3b33e25..516debed 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -544,23 +544,23 @@ print("Name: \(BookName.john.rawValue)") // Enum with associated Values enum Furniture { // Associate with Int - case Desk(height: Int) + case desk(height: Int) // Associate with String and Int - case Chair(String, Int) + case chair(String, Int) func description() -> String { switch self { - case .Desk(let height): + case .desk(let height): return "Desk with \(height) cm" - case .Chair(let brand, let height): + case .chair(let brand, let height): return "Chair of \(brand) with \(height) cm" } } } -var desk: Furniture = .Desk(height: 80) +var desk: Furniture = .desk(height: 80) print(desk.description()) // "Desk with 80 cm" -var chair = Furniture.Chair("Foo", 40) +var chair = Furniture.chair("Foo", 40) print(chair.description()) // "Chair of Foo with 40 cm" -- cgit v1.2.3 From 175a78ec331b6d28e5940206f6f3e884405a858d Mon Sep 17 00:00:00 2001 From: Joseph G Date: Thu, 11 Oct 2018 14:21:54 -0700 Subject: Removed deprecated reference --- swift.html.markdown | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 516debed..f834f373 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -13,9 +13,9 @@ filename: learnswift.swift Swift is a programming language for iOS and OS X development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+. -The official [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) book from Apple is now available via iBooks. +The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks. -See also Apple's [getting started guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/DevelopiOSAppsSwift/), which has a complete tutorial on Swift. +Another great reference is _About Swift_ on Swift's [website](https://docs.swift.org/swift-book/). ```swift // import a module -- cgit v1.2.3 From 84cb0296175c3c8524d00edf23b90bf45e01fd35 Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Sat, 3 Aug 2019 07:13:22 -0400 Subject: [Swift/en] Update to Swift 5 and include omitted examples (#3553) * Update to Swift 5 and include omitted examples * Reformat lines to ~80 characters * Fix mistype and add optional chaining --- swift.html.markdown | 988 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 647 insertions(+), 341 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index f834f373..48e0f6f2 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -8,22 +8,26 @@ contributors: - ["Clayton Walker", "https://github.com/cwalk"] - ["Fernando Valverde", "http://visualcosita.xyz"] - ["Alexey Nazaroff", "https://github.com/rogaven"] + - ["@Samasaur1", "https://github.com/Samasaur1"] filename: learnswift.swift --- Swift is a programming language for iOS and OS X development created by Apple. Designed to coexist with Objective-C and to be more resilient against erroneous code, Swift was introduced in 2014 at Apple's developer conference WWDC. It is built with the LLVM compiler included in Xcode 6+. -The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks. +The official _[Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329)_ book from Apple is now available via iBooks. It goes into much more detail than this guide, and if you have the time and patience to read it, it's recommended. Some of these examples are from that book. Another great reference is _About Swift_ on Swift's [website](https://docs.swift.org/swift-book/). ```swift // import a module -import UIKit +import Foundation -// -// MARK: Basics -// +// Single-line comments are prefixed with // +// Multi-line comments start with /* and end with */ +/* Nested multiline comments + /* ARE */ + allowed + */ // Xcode supports landmarks to annotate your code and lists them in the jump bar // MARK: Section mark @@ -31,220 +35,380 @@ import UIKit // TODO: Do something soon // FIXME: Fix this code -// In Swift 2, println and print were combined into one print method. Print automatically appends a new line. -print("Hello, world") // println is now print -print("Hello, world", terminator: "") // printing without appending a newline +//MARK: Hello, World +// From Swift 3 on, to print, just use the `print` method. +// It automatically appends a new line. +print("Hello, world") + +// +// MARK: - Variables +// + + +//Use `let` to declare a constant and `var` to declare a variable. +let theAnswer = 42 +var theQuestion = "What is the Answer?" +theQuestion = "How many roads must a man walk down?" +theQuestion = "What is six by nine?" +// Atttempting to reassign a constant throws a compile-time error +//theAnswer = 54 + +// Both variables and constants can be declared before they are given a value, +// but must be given a value before they are used +let someConstant: Int +var someVariable: String +// These lines will throw errors: +//print(someConstant) +//print(someVariable) +someConstant = 0 +someVariable = "0" + +// As you can see above, variable types are automatically inferred. +// To explicitly declare the type, write it after the variable name, +// separated by a colon. +let aString: String = "A string" +let aDouble: Double = 0 + +// Values are never implicitly converted to another type. +// Explicitly make instances of the desired type. +let stringWithDouble = aString + String(aDouble) +let intFromDouble = Int(aDouble) + +// For strings, use string interpolation +let descriptionString = "The value of aDouble is \(aDouble)" +// You can put any expression inside string interpolation. +let equation = "Six by nine is \(6 * 9), not 42!" +// To avoid escaping double quotes and backslashes, change the string delimiter +let explanationString = #"The string I used was "The value of aDouble is \(aDouble)" and the result was \#(descriptionString)"# +// You can put as many number signs as you want before the opening quote, +// just match them at the ending quote. They also change the escape character +// to a backslash followed by the same number of number signs. + +let multiLineString = """ + This is a multi-line string. + It's called that because it takes up multiple lines (wow!) + Any indentation beyond the closing quotation marks is kept, the rest is discarded. + You can include " or "" in multi-line strings because the delimeter is three. + """ + +// Arrays +let shoppingList = ["catfish", "water", "tulips",] //commas are allowed after the last element +let secondElement = shoppingList[1] // Arrays are 0-indexed + +// Arrays declared with let are immutable; the following line throws a compile-time error +//shoppingList[2] = "mango" + +// Arrays are structs (more on that later), so this creates a copy instead of referencing the same object +var mutableShoppingList = shoppingList +mutableShoppingList[2] = "mango" + +// == is equality +shoppingList == mutableShoppingList // false + +// Dictionaries declared with let are also immutable +var occupations = [ + "Malcolm": "Captain", + "kaylee": "Mechanic" +] +occupations["Jayne"] = "Public Relations" +// Dictionaries are also structs, so this also creates a copy +let immutableOccupations = occupations -// variables (var) value can change after being set -// constants (let) value can NOT be changed after being set +immutableOccupations == occupations // true -var myVariable = 42 +// Arrays and dictionaries both automatically grow as you add elements +mutableShoppingList.append("blue paint") +occupations["Tim"] = "CEO" + +// They can both be set to empty +mutableShoppingList = [] +occupations = [:] + +let emptyArray = [String]() +let emptyArray2 = Array() // same as above +// [T] is shorthand for Array +let emptyArray3: [String] = [] // Declaring the type explicitly allows you to set it to an empty array +let emptyArray4: Array = [] // same as above + +// [Key: Value] is shorthand for Dictionary +let emptyDictionary = [String: Double]() +let emptyDictionary2 = Dictionary() // same as above +var emptyMutableDictionary: [String: Double] = [:] +var explicitEmptyMutableDictionary: Dictionary = [:] // same as above + +// MARK: Other variables let øπΩ = "value" // unicode variable names -let π = 3.1415926 -let convenience = "keyword" // contextual variable name -let weak = "keyword"; let override = "another keyword" // statements can be separated by a semi-colon -let `class` = "keyword" // backticks allow keywords to be used as variable names -let explicitDouble: Double = 70 -let intValue = 0007 // 7 -let largeIntValue = 77_000 // 77000 -let label = "some text " + String(myVariable) // String construction -let piText = "Pi = \(π), Pi 2 = \(π * 2)" // String interpolation - -// Build Specific values -// uses -D build configuration -#if false - print("Not printed") - let buildValue = 3 -#else - let buildValue = 7 -#endif -print("Build value: \(buildValue)") // Build value: 7 +let 🤯 = "wow" // emoji variable names -/* -Optionals are a Swift language feature that either contains a value, -or contains nil (no value) to indicate that a value is missing. -A question mark (?) after the type marks the value as optional. +// Keywords can be used as variable names +// These are contextual keywords that wouldn't be used now, so are allowed +let convenience = "keyword" +let weak = "another keyword" +let override = "another keyword" -Because Swift requires every property to have a value, even nil must be -explicitly stored as an Optional value. +// Using backticks allows keywords to be used as variable names even if they wouldn't be allowed normally +let `class` = "keyword" + +// MARK: - Optionals + +/* + Optionals are a Swift language feature that either contains a value, + or contains nil (no value) to indicate that a value is missing. + Nil is roughly equivalent to `null` in other languages. + A question mark (?) after the type marks the value as optional of that type. + + If a type is not optional, it is guaranteed to have a value. + + Because Swift requires every property to have a type, even nil must be + explicitly stored as an Optional value. + + Optional is an enum, with the cases .none (nil) and .some(T) (the value) + */ -Optional is an enum. -*/ var someOptionalString: String? = "optional" // Can be nil -// same as above, but ? is a postfix operator (syntax candy) -var someOptionalString2: Optional = "optional" +// T? is shorthand for Optional — ? is a postfix operator (syntax candy) +let someOptionalString2: Optional = nil +let someOptionalString3 = String?.some("optional") // same as the first one +let someOptionalString4 = String?.none //nil + +/* + To access the value of an optional that has a value, use the postfix + operator !, which force-unwraps it. Force-unwrapping is like saying, "I + know that this optional definitely has a value, please give it to me. + + Trying to use ! to access a non-existent optional value triggers a + runtime error. Always make sure that an optional contains a non-nil + value before using ! to force-unwrap its value. + */ if someOptionalString != nil { // I am not nil if someOptionalString!.hasPrefix("opt") { print("has the prefix") } - - let empty = someOptionalString?.isEmpty } -someOptionalString = nil -/* -Trying to use ! to access a non-existent optional value triggers a runtime -error. Always make sure that an optional contains a non-nil value before -using ! to force-unwrap its value. -*/ - -// implicitly unwrapped optional -var unwrappedString: String! = "Value is expected." -// same as above, but ! is a postfix operator (more syntax candy) -var unwrappedString2: ImplicitlyUnwrappedOptional = "Value is expected." - -// If let structure - -// If let is a special structure in Swift that allows you to check if an Optional rhs holds a value, and in case it does - unwraps and assigns it to the lhs. -if let someOptionalStringConstant = someOptionalString { +// Swift supports "optional chaining," which means that you can call functions +// or get properties of optional values and they are optionals of the appropriate type. +// You can even do this multiple times, hence the name "chaining." + +let empty = someOptionalString?.isEmpty // Bool? + +// if-let structure - +// if-let is a special structure in Swift that allows you to check +// if an Optional rhs holds a value, and if it does unwrap +// and assign it to the lhs. +if let someNonOptionalStringConstant = someOptionalString { // has `Some` value, non-nil - if !someOptionalStringConstant.hasPrefix("ok") { + // someOptionalStringConstant is of type String, not type String? + if !someNonOptionalStringConstant.hasPrefix("ok") { // does not have the prefix } } -// The nil-coalescing operator ?? unwraps an optional if it contains a non-nil value, or returns a default value. -var someOptionalString: String? -let someString = someOptionalString ?? "abc" -print(someString) // abc +//if-var is allowed too! +if var someNonOptionalString = someOptionalString { + someNonOptionalString = "Non optional AND mutable" + print(someNonOptionalString) +} -// Swift has support for storing a value of any type. -// For that purposes there is two keywords: `Any` and `AnyObject` -// `AnyObject` == `id` from Objective-C -// `Any` – also works with any scalar values (Class, Int, struct, etc.) -var anyVar: Any = 7 -anyVar = "Changed value to a string, not good practice, but possible." -let anyObjectVar: AnyObject = Int(1) as NSNumber +// You can bind multiple optional values in one if-let statement. +// If any of the bound values are nil, the if statement does not execute. +if let first = someOptionalString, let second = someOptionalString2, + let third = someOptionalString3, let fourth = someOptionalString4 { + print("\(first), \(second), \(third), and \(fourth) are all not nil") +} -/* - Comment here +//if-let supports "," (comma) clauses, which can be used to +// enforce conditions on newly-bound optional values. +// Both the assignment and the "," clause must pass. +let someNumber: Int? = 7 +if let num = someNumber, num > 3 { + print("num is not nil and is greater than 3") +} - /* - Nested comments are also supported - */ -*/ +// Implicitly unwrapped optional — An optional value that doesn't need to be unwrapped +let unwrappedString: String! = "Value is expected." -// -// MARK: Collections -// +// Here's the difference: +let forcedString = someOptionalString! // requires an exclamation mark +let implicitString = unwrappedString // doesn't require an exclamation mark /* -Array and Dictionary types are structs. So `let` and `var` also indicate -that they are mutable (var) or immutable (let) when declaring these types. -*/ - -// Array -var shoppingList = ["catfish", "water", "lemons"] -shoppingList[1] = "bottle of water" -let emptyArray = [String]() // let == immutable -let emptyArray2 = Array() // same as above -var emptyMutableArray = [String]() // var == mutable -var explicitEmptyMutableStringArray: [String] = [] // same as above - + You can think of an implicitly unwrapped optional as giving permission + for the optional to be unwrapped automatically whenever it's used. + Rather than placing an exclamation mark after the optional's name each time you use it, + you place an exclamation mark after the optional's type when you declare it. + */ -// Dictionary -var occupations = [ - "Malcolm": "Captain", - "kaylee": "Mechanic" -] -occupations["Jayne"] = "Public Relations" -let emptyDictionary = [String: Float]() // let == immutable -let emptyDictionary2 = Dictionary() // same as above -var emptyMutableDictionary = [String: Float]() // var == mutable -var explicitEmptyMutableDictionary: [String: Float] = [:] // same as above - - -// -// MARK: Control Flow -// +// Otherwise, you can treat an implicitly unwrapped optional the same way the you treat a normal optional +// (i.e., if-let, != nil, etc.) -// Condition statements support "," (comma) clauses, which can be used -// to help provide conditions on optional values. -// Both the assignment and the "," clause must pass. -let someNumber = Optional(7) -if let num = someNumber, num > 3 { - print("num is greater than 3") -} +// Pre-Swift 5, T! was shorthand for ImplicitlyUnwrappedOptional +// Swift 5 and later, using ImplicitlyUnwrappedOptional throws a compile-time error. +//var unwrappedString2: ImplicitlyUnwrappedOptional = "Value is expected." //error -// for loop (array) -let myArray = [1, 1, 2, 3, 5] -for value in myArray { - if value == 1 { - print("One!") - } else { - print("Not one!") - } -} +// The nil-coalescing operator ?? unwraps an optional if it contains a non-nil value, or returns a default value. +someOptionalString = nil +let someString = someOptionalString ?? "abc" +print(someString) // abc +// a ?? b is shorthand for a != nil ? a! : b -// for loop (dictionary) -var dict = ["one": 1, "two": 2] -for (key, value) in dict { - print("\(key): \(value)") -} +// MARK: - Control Flow -// for loop (range) -for i in -1...shoppingList.count { - print(i) -} -shoppingList[1...2] = ["steak", "peacons"] -// use ..< to exclude the last number +let condition = true +if condition { print("condition is true") } // can't omit the braces -// while loop -var i = 1 -while i < 1000 { - i *= 2 +if theAnswer > 50 { + print("theAnswer > 50") +} else if condition { + print("condition is true") +} else { + print("Neither are true") } -// repeat-while loop -repeat { - print("hello") -} while 1 == 2 +// The condition in an `if` statement must be a `Bool`, so the following code is an error, not an implicit comparison to zero +//if 5 { +// print("5 is not zero") +//} // Switch +// Must be exhaustive +// Does not implicitly fall through, use the fallthrough keyword // Very powerful, think `if` statements with syntax candy // They support String, object instances, and primitives (Int, Double, etc) let vegetable = "red pepper" +let vegetableComment: String switch vegetable { case "celery": - let vegetableComment = "Add some raisins and make ants on a log." -case "cucumber", "watercress": - let vegetableComment = "That would make a good tea sandwich." + vegetableComment = "Add some raisins and make ants on a log." +case "cucumber", "watercress": // match multiple values + vegetableComment = "That would make a good tea sandwich." case let localScopeValue where localScopeValue.hasSuffix("pepper"): - let vegetableComment = "Is it a spicy \(localScopeValue)?" + vegetableComment = "Is it a spicy \(localScopeValue)?" default: // required (in order to cover all possible input) - let vegetableComment = "Everything tastes good in soup." + vegetableComment = "Everything tastes good in soup." +} +print(vegetableComment) + +// You use the `for-in` loop to iterate over a sequence, such as an array, dictionary, range, etc. +for element in shoppingList { + print(element) // shoppingList is of type `[String]`, so element is of type `String` +} +//Iterating through a dictionary does not guarantee any specific order +for (person, job) in immutableOccupations { + print("\(person)'s job is \(job)") +} +for i in 1...5 { + print(i, terminator: " ") // Prints "1 2 3 4 5" +} +for i in 0..<5 { + print(i, terminator: " ") // Prints "0 1 2 3 4" +} +//for index in range can replace a C-style for loop: +// for (int i = 0; i < 10; i++) { +// //code +// } +//becomes: +// for i in 0..<10 { +// //code +// } +//To step by more than one, use the stride(from:to:by:) or stride(from:through:by) functions +//`for i in stride(from: 0, to: 10, by: 2)` is the same as `for (int i = 0; i < 10; i += 2)` +//`for i in stride(from: 0, through: 10, by: 2)` is the same as `for (int i = 0; i <= 10; i += 2) + +// while loops are just like most languages +var i = 0 +while i < 5 { + i += Bool.random() ? 1 : 0 + print(i) } -// -// MARK: Functions -// +// This is like a do-while loop in other languages — the body of the loop executes a minimum of once +repeat { + i -= 1 + i += Int.random(in: 0...3) +} while i < 5 -// Functions are a first-class type, meaning they can be nested -// in functions and can be passed around +// The continue statement continues executing a loop at the next iteration +// The break statement ends a swift or loop immediately -// Function with Swift header docs (format as Swift-modified Markdown syntax) +// MARK: - Functions -/** -A greet operation +// Functions are a first-class type, meaning they can be nested in functions and can be passed around. -- A bullet in docs -- Another bullet in the docs +// Function with Swift header docs (format as Swift-modified Markdown syntax) -- Parameter name : A name -- Parameter day : A day -- Returns : A string containing the name and day value. -*/ +/// A greet operation. +/// +/// - Parameters: +/// - name: A name. +/// - day: A day. +/// - Returns: A string containing the name and day value. func greet(name: String, day: String) -> String { return "Hello \(name), today is \(day)." } greet(name: "Bob", day: "Tuesday") -// similar to above except for the function parameter behaviors -func greet2(name: String, externalParamName localParamName: String) -> String { - return "Hello \(name), the day is \(localParamName)" +// Ideally, function names and parameter labels combine to make function calls similar to sentences. +func sayHello(to name: String, onDay day: String) -> String { + return "Hello \(name), the day is \(day)" +} +sayHello(to: "John", onDay: "Sunday") + +//Functions that don't return anything can omit the return arrow; they don't need to say that they return Void (although they can). +func helloWorld() { + print("Hello, World!") +} + +// Argument labels can be blank +func say(_ message: String) { + print(#"I say "\#(message)""#) +} +say("Hello") + +// Default parameters can be ommitted when calling the function. +func printParameters(requiredParameter r: Int, optionalParameter o: Int = 10) { + print("The required parameter was \(r) and the optional parameter was \(o)") +} +printParameters(requiredParameter: 3) +printParameters(requiredParameter: 3, optionalParameter: 6) + +// Variadic args — only one set per function. +func setup(numbers: Int...) { + // it's an array + let _ = numbers[0] + let _ = numbers.count +} + +// pass by ref +func swapTwoInts(a: inout Int, b: inout Int) { + let tempA = a + a = b + b = tempA +} +var someIntA = 7 +var someIntB = 3 +swapTwoInts(a: &someIntA, b: &someIntB) //must be called with an & before the variable name. +print(someIntB) // 7 + +type(of: greet) // (String, String) -> String +type(of: helloWorld) // () -> Void + +// Passing and returning functions +func makeIncrementer() -> ((Int) -> Int) { + func addOne(number: Int) -> Int { + return 1 + number + } + return addOne +} +var increment = makeIncrementer() +increment(7) + +func performFunction(_ function: (String, String) -> String, on string1: String, and string2: String) { + let result = function(string1, string2) + print("The result of calling the function on \(string1) and \(string2) was \(result)") } -greet2(name: "John", externalParamName: "Sunday") // Function that returns multiple items in a tuple func getGasPrices() -> (Double, Double, Double) { @@ -271,46 +435,24 @@ print("Highest gas price: \(pricesTuple2.highestPrice)") func testGuard() { // guards provide early exits or breaks, placing the error handler code near the conditions. // it places variables it declares in the same scope as the guard statement. + // They make it easier to avoid the "pyramid of doom" guard let aNumber = Optional(7) else { - return + return // guard statements MUST exit the scope that they are in. + // They generally use `return` or `throw`. } - + print("number is \(aNumber)") } testGuard() -// Variadic Args -func setup(numbers: Int...) { - // it's an array - let _ = numbers[0] - let _ = numbers.count -} +// Note that the print function is declared like so: +// func print(_ input: Any..., separator: String = " ", terminator: String = "\n") +// To print without a newline: +print("No newline", terminator: "") +print("!") -// Passing and returning functions -func makeIncrementer() -> ((Int) -> Int) { - func addOne(number: Int) -> Int { - return 1 + number - } - return addOne -} -var increment = makeIncrementer() -increment(7) +// MARK: - Closures -// pass by ref -func swapTwoInts(a: inout Int, b: inout Int) { - let tempA = a - a = b - b = tempA -} -var someIntA = 7 -var someIntB = 3 -swapTwoInts(a: &someIntA, b: &someIntB) -print(someIntB) // 7 - - -// -// MARK: Closures -// var numbers = [1, 2, 6] // Functions are special case closures ({}) @@ -336,85 +478,157 @@ numbers = numbers.sorted { $0 > $1 } print(numbers) // [18, 6, 3] -// -// MARK: Structures -// +// MARK: - Enums -// Structures and classes have very similar capabilities -struct NamesTable { - let names: [String] +// Enums can optionally be of a specific type or on their own. +// They can contain methods like classes. - // Custom subscript - subscript(index: Int) -> String { - return names[index] +enum Suit { + case spades, hearts, diamonds, clubs + var icon: Character { + switch self { + case .spades: + return "♤" + case .hearts: + return "♡" + case .diamonds: + return "♢" + case .clubs: + return "♧" + } } } -// Structures have an auto-generated (implicit) designated initializer -let namesTable = NamesTable(names: ["Me", "Them"]) -let name = namesTable[1] -print("Name is \(name)") // Name is Them - -// -// MARK: Error Handling -// +// Enum values allow short hand syntax, no need to type the enum type +// when the variable is explicitly declared +var suitValue: Suit = .hearts -// The `Error` protocol is used when throwing errors to catch -enum MyError: Error { - case badValue(msg: String) - case reallyBadValue(msg: String) +// Conforming to the CaseIterable protocol automatically synthesizes the allCases property, +// which contains all the values. It works on enums without associated values or @available attributes. +enum Rank: CaseIterable { + case ace + case two, three, four, five, six, seven, eight, nine, ten + case jack, queen, king + var icon: String { + switch self { + case .ace: + return "A" + case .two: + return "2" + case .three: + return "3" + case .four: + return "4" + case .five: + return "5" + case .six: + return "6" + case .seven: + return "7" + case .eight: + return "8" + case .nine: + return "9" + case .ten: + return "10" + case .jack: + return "J" + case .queen: + return "Q" + case .king: + return "K" + } + } } -// functions marked with `throws` must be called using `try` -func fakeFetch(value: Int) throws -> String { - guard 7 == value else { - throw MyError.reallyBadValue(msg: "Some really bad value") +for suit in [Suit.clubs, .diamonds, .hearts, .spades] { + for rank in Rank.allCases { + print("\(rank.icon)\(suit.icon)") } +} - return "test" +// String enums can have direct raw value assignments +// or their raw values will be derived from the Enum field +enum BookName: String { + case john + case luke = "Luke" } +print("Name: \(BookName.john.rawValue)") -func testTryStuff() { - // assumes there will be no error thrown, otherwise a runtime exception is raised - let _ = try! fakeFetch(value: 7) +// Enum with associated Values +enum Furniture { + // Associate with Int + case desk(height: Int) + // Associate with String and Int + case chair(String, Int) + + func description() -> String { + //either placement of let is acceptable + switch self { + case .desk(let height): + return "Desk with \(height) cm" + case let .chair(brand, height): + return "Chair of \(brand) with \(height) cm" + } + } +} - // if an error is thrown, then it proceeds, but if the value is nil - // it also wraps every return value in an optional, even if its already optional - let _ = try? fakeFetch(value: 7) +var desk: Furniture = .desk(height: 80) +print(desk.description()) // "Desk with 80 cm" +var chair = Furniture.chair("Foo", 40) +print(chair.description()) // "Chair of Foo with 40 cm" - do { - // normal try operation that provides error handling via `catch` block - try fakeFetch(value: 1) - } catch MyError.badValue(let msg) { - print("Error message: \(msg)") - } catch { - // must be exhaustive +// MARK: - Structures & Classes + +/* + Structures and classes in Swift have many things in common. Both can: + - Define properties to store values + - Define methods to provide functionality + - Define subscripts to provide access to their values using subscript syntax + - Define initializers to set up their initial state + - Be extended to expand their functionality beyond a default implementation + - Conform to protocols to provide standard functionality of a certain kind + + Classes have additional capabilities that structures don't have: + - Inheritance enables one class to inherit the characteristics of another. + - Type casting enables you to check and interpret the type of a class instance at runtime. + - Deinitializers enable an instance of a class to free up any resources it has assigned. + - Reference counting allows more than one reference to a class instance. + + Unless you need to use a class for one of these reasons, use a struct. + + Structures are value types, while classes are reference types. + */ + +// MARK: Structures + +struct NamesTable { + let names: [String] + + // Custom subscript + subscript(index: Int) -> String { + return names[index] } } -testTryStuff() -// -// MARK: Classes -// +// Structures have an auto-generated (implicit) designated "memberwise" initializer +let namesTable = NamesTable(names: ["Me", "Them"]) +let name = namesTable[1] +print("Name is \(name)") // Name is Them -// Classes, structures and its members have three levels of access control -// They are: internal (default), public, private +// MARK: Classes -public class Shape { - public func getArea() -> Int { +class Shape { + func getArea() -> Int { return 0 } } -// All methods and properties of a class are public. -// If you just need to store data in a -// structured object, you should use a `struct` - -internal class Rect: Shape { +class Rect: Shape { var sideLength: Int = 1 - + // Custom getter and setter property - private var perimeter: Int { + var perimeter: Int { get { return 4 * sideLength } @@ -423,16 +637,16 @@ internal class Rect: Shape { sideLength = newValue / 4 } } - + // Computed properties must be declared as `var`, you know, cause' they can change var smallestSideLength: Int { return self.sideLength - 1 } - + // Lazily load a property // subShape remains nil (uninitialized) until getter called lazy var subShape = Rect(sideLength: 4) - + // If you don't need a custom getter and setter, // but still want to run code before and after getting or setting // a property, you can use `willSet` and `didSet` @@ -442,19 +656,19 @@ internal class Rect: Shape { print(someIdentifier) } } - + init(sideLength: Int) { self.sideLength = sideLength // always super.init last when init custom properties super.init() } - + func shrink() { if sideLength > 0 { sideLength -= 1 } } - + override func getArea() -> Int { return sideLength * sideLength } @@ -486,13 +700,13 @@ class Circle: Shape { override func getArea() -> Int { return 3 * radius * radius } - + // Place a question mark postfix after `init` is an optional init // which can return nil init?(radius: Int) { self.radius = radius super.init() - + if radius <= 0 { return nil } @@ -509,104 +723,143 @@ if let circle = myEmptyCircle { print("circle is not nil") } +// MARK: - Protocols -// -// MARK: Enums -// +// protocols are also known as interfaces in some other languages -// Enums can optionally be of a specific type or on their own. -// They can contain methods like classes. +// `protocol`s can require that conforming types have specific +// instance properties, instance methods, type methods, +// operators, and subscripts. -enum Suit { - case spades, hearts, diamonds, clubs - func getIcon() -> String { - switch self { - case .spades: return "♤" - case .hearts: return "♡" - case .diamonds: return "♢" - case .clubs: return "♧" - } - } +protocol ShapeGenerator { + var enabled: Bool { get set } + func buildShape() -> Shape } -// Enum values allow short hand syntax, no need to type the enum type -// when the variable is explicitly declared -var suitValue: Suit = .hearts +// MARK: - Other -// String enums can have direct raw value assignments -// or their raw values will be derived from the Enum field -enum BookName: String { - case john - case luke = "Luke" -} -print("Name: \(BookName.john.rawValue)") +// MARK: Typealiases -// Enum with associated Values -enum Furniture { - // Associate with Int - case desk(height: Int) - // Associate with String and Int - case chair(String, Int) +// Typealiases allow one type (or composition of types) to be referred to by another name +typealias Integer = Int +let myInteger: Integer = 0 - func description() -> String { - switch self { - case .desk(let height): - return "Desk with \(height) cm" - case .chair(let brand, let height): - return "Chair of \(brand) with \(height) cm" - } - } -} +// MARK: = Operator -var desk: Furniture = .desk(height: 80) -print(desk.description()) // "Desk with 80 cm" -var chair = Furniture.chair("Foo", 40) -print(chair.description()) // "Chair of Foo with 40 cm" +// Assignment does not return a value. This means it can't be used in conditional statements, +// and the following statement is also illegal +// let multipleAssignment = theQuestion = "No questions asked" +//But you can do this: +let multipleAssignment = "No questions asked", secondConstant = "No answers given" +// MARK: Ranges -// -// MARK: Protocols -// +// The ..< and ... operators create ranges. -// `protocol`s can require that conforming types have specific -// instance properties, instance methods, type methods, -// operators, and subscripts. +// ... is inclusive on both ends (a "closed range") — mathematically, [0, 10] +let _0to10 = 0...10 +// ..< in inclusive on the left, exclusive on the right (a "range") — mathematically, [0, 10) +let singleDigitNumbers = 0..<10 +// You can omit one end (a "PartialRangeFrom") — mathematically, [0, ∞) +let toInfinityAndBeyond = 0... +// Or the other end (a "PartialRangeTo") — mathematically, (-∞, 0) +let negativeInfinityToZero = ..<0 +// (a "PartialRangeThrough") — mathematically, (-∞, 0] +let negativeInfinityThroughZero = ...0 -protocol ShapeGenerator { - var enabled: Bool { get set } - func buildShape() -> Shape +// MARK: Wildcard operator + +// In Swift, _ (underscore) is the wildcard operator, which allows values to be ignored + +// It allows functions to be declared without argument labels: +func function(_ labelLessParameter: Int, label labeledParameter: Int, labelAndParameterName: Int) { + print(labelLessParameter, labeledParameter, labelAndParameterName) } +function(0, label: 0, labelAndParameterName: 0) -// Protocols declared with @objc allow optional functions, -// which allow you to check for conformance. These functions must be -// marked with @objc also. -@objc protocol TransformShape { - @objc optional func reshape() - @objc optional func canReshape() -> Bool +// You can ignore the return values of functions +func printAndReturn(_ str: String) -> String { + print(str) + return str } +let _ = printAndReturn("Some String") -class MyShape: Rect { - var delegate: TransformShape? +// You can ignore part of a tuple and keep part of it +func returnsTuple() -> (Int, Int) { + return (1, 2) +} +let (_, two) = returnsTuple() - func grow() { - sideLength += 2 +// You can ignore closure parameters +let closure: (Int, Int) -> String = { someInt, _ in + return "\(someInt)" +} +closure(1, 2) // returns 1 - // Place a question mark after an optional property, method, or - // subscript to gracefully ignore a nil value and return nil - // instead of throwing a runtime error ("optional chaining"). - if let reshape = self.delegate?.canReshape?(), reshape { - // test for delegate then for method - self.delegate?.reshape?() - } - } +// You can ignore the value in a for loop +for _ in 0..<10 { + // Code to execute 10 times } +// MARK: Access Control -// -// MARK: Other -// +/* + Swift has five levels of access control: + - Open: Accessible *and subclassible* in any module that imports it. + - Public: Accessible in any module that imports it, subclassible in the module it is declared in. + - Internal: Accessible and subclassible in the module it is declared in. + - Fileprivate: Accessible and subclassible in the file it is declared in. + - Private: Accessible and subclassible in the enclosing declaration (think inner classes) + + See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html + */ + +// MARK: Conditional Compilation, Compile-Time Diagnostics, & Availability Conditions + +// Conditional Compilation +#if false +print("This code will not be compiled") +#else +print("This code will be compiled") +#endif +/* + Options are: + os() macOS, iOS, watchOS, tvOS, Linux + arch() i386, x86_64, arm, arm64 + swift() >= or < followed by a version number + compiler() >= or < followed by a version number + canImport() A module name + targetEnvironment() simulator + */ +#if swift(<3) +println() +#endif + +// Compile-Time Diagnostics +// You can use #warning(message) and #error(message) to have the compiler emit warnings and/or errors +#warning("This will be a compile-time warning") +// #error("This would be a compile-time error") -// `extension`s: Add extra functionality to an already existing type +//Availability Conditions +if #available(iOSMac 10.15, *) { + // macOS 10.15 is available, you can use it here +} else { + // macOS 10.15 is not available, use alternate APIs +} + +// MARK: Any and AnyObject + +// Swift has support for storing a value of any type. +// For that purpose there are two keywords: `Any` and `AnyObject` +// `AnyObject` == `id` from Objective-C +// `Any` works with any values (class, Int, struct, etc.) +var anyVar: Any = 7 +anyVar = "Changed value to a string, not good practice, but possible." +let anyObjectVar: AnyObject = Int(1) as NSNumber + +// MARK: Extensions + +// Extensions allow you to add extra functionality to an already-declared type, even one that you don't have the source code for. // Square now "conforms" to the `CustomStringConvertible` protocol extension Square: CustomStringConvertible { @@ -619,17 +872,23 @@ print("Square: \(mySquare)") // You can also extend built-in types extension Int { - var customProperty: String { - return "This is \(self)" + var doubled: Int { + return self * 2 } - - func multiplyBy(num: Int) -> Int { + + func multipliedBy(num: Int) -> Int { return num * self } + + mutating func multiplyBy(num: Int) { + self *= num + } } -print(7.customProperty) // "This is 7" -print(14.multiplyBy(num: 3)) // 42 +print(7.doubled) // 14 +print(7.doubled.multipliedBy(num: 3)) // 42 + +// MARK: Generics // Generics: Similar to Java and C#. Use the `where` keyword to specify the // requirements of the generics. @@ -642,10 +901,21 @@ func findIndex(array: [T], valueToFind: T) -> Int? { } return nil } -let foundAtIndex = findIndex(array: [1, 2, 3, 4], valueToFind: 3) -print(foundAtIndex == 2) // true +findIndex(array: [1, 2, 3, 4], valueToFind: 3) // 2 + +// You can extend types with generics as well +extension Array where Array.Element == Int { + var sum: Int { + var total = 0 + for el in self { + total += el + } + return total + } +} + +// MARK: Operators -// Operators: // Custom operators can start with the characters: // / = - + * % < > ! & | ^ . ~ // or @@ -678,4 +948,40 @@ var bar: Float = 20 foo <-> bar print("foo is \(foo), bar is \(bar)") // "foo is 20.0, bar is 10.0" + +// MARK: - Error Handling + +// The `Error` protocol is used when throwing errors to catch +enum MyError: Error { + case badValue(msg: String) + case reallyBadValue(msg: String) +} + +// functions marked with `throws` must be called using `try` +func fakeFetch(value: Int) throws -> String { + guard 7 == value else { + throw MyError.reallyBadValue(msg: "Some really bad value") + } + + return "test" +} + +func testTryStuff() { + // assumes there will be no error thrown, otherwise a runtime exception is raised + let _ = try! fakeFetch(value: 7) + + // if an error is thrown, then it proceeds, but if the value is nil + // it also wraps every return value in an optional, even if its already optional + let _ = try? fakeFetch(value: 7) + + do { + // normal try operation that provides error handling via `catch` block + try fakeFetch(value: 1) + } catch MyError.badValue(let msg) { + print("Error message: \(msg)") + } catch { + // must be exhaustive + } +} +testTryStuff() ``` -- cgit v1.2.3 From fb579b88f47cbc4324644cdd2767023243a2d75c Mon Sep 17 00:00:00 2001 From: Sam <30577766+Samasaur1@users.noreply.github.com> Date: Sat, 3 Aug 2019 10:38:55 -0400 Subject: [Swift/en] Fix quoted multi-line string The renderer on the website doesn't recognize Swift multi-line strings, so a bunch of the file was treated as a string literal. This adds another " in the multi-line string to balance it out --- swift.html.markdown | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 48e0f6f2..c2fb3471 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -62,6 +62,9 @@ var someVariable: String //print(someVariable) someConstant = 0 someVariable = "0" +// These lines are now valid: +print(someConstant) +print(someVariable) // As you can see above, variable types are automatically inferred. // To explicitly declare the type, write it after the variable name, @@ -88,7 +91,7 @@ let multiLineString = """ This is a multi-line string. It's called that because it takes up multiple lines (wow!) Any indentation beyond the closing quotation marks is kept, the rest is discarded. - You can include " or "" in multi-line strings because the delimeter is three. + You can include " or "" in multi-line strings because the delimeter is three "s. """ // Arrays @@ -108,7 +111,7 @@ shoppingList == mutableShoppingList // false // Dictionaries declared with let are also immutable var occupations = [ "Malcolm": "Captain", - "kaylee": "Mechanic" + "Kaylee": "Mechanic" ] occupations["Jayne"] = "Public Relations" // Dictionaries are also structs, so this also creates a copy @@ -174,7 +177,7 @@ let someOptionalString4 = String?.none //nil /* To access the value of an optional that has a value, use the postfix operator !, which force-unwraps it. Force-unwrapping is like saying, "I - know that this optional definitely has a value, please give it to me. + know that this optional definitely has a value, please give it to me." Trying to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil @@ -758,7 +761,7 @@ let multipleAssignment = "No questions asked", secondConstant = "No answers give // ... is inclusive on both ends (a "closed range") — mathematically, [0, 10] let _0to10 = 0...10 -// ..< in inclusive on the left, exclusive on the right (a "range") — mathematically, [0, 10) +// ..< is inclusive on the left, exclusive on the right (a "range") — mathematically, [0, 10) let singleDigitNumbers = 0..<10 // You can omit one end (a "PartialRangeFrom") — mathematically, [0, ∞) let toInfinityAndBeyond = 0... @@ -809,7 +812,7 @@ for _ in 0..<10 { - Public: Accessible in any module that imports it, subclassible in the module it is declared in. - Internal: Accessible and subclassible in the module it is declared in. - Fileprivate: Accessible and subclassible in the file it is declared in. - - Private: Accessible and subclassible in the enclosing declaration (think inner classes) + - Private: Accessible and subclassible in the enclosing declaration (think inner classes/structs/enums) See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html */ -- cgit v1.2.3 From db010c8a72a3390461fea62db0890e9f986993bd Mon Sep 17 00:00:00 2001 From: Hugo Locurcio Date: Tue, 22 Oct 2019 09:10:07 +0200 Subject: [swift/en] Fix typos --- swift.html.markdown | 56 ++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 28 deletions(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index c2fb3471..1f9fe897 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -91,7 +91,7 @@ let multiLineString = """ This is a multi-line string. It's called that because it takes up multiple lines (wow!) Any indentation beyond the closing quotation marks is kept, the rest is discarded. - You can include " or "" in multi-line strings because the delimeter is three "s. + You can include " or "" in multi-line strings because the delimiter is three "s. """ // Arrays @@ -159,12 +159,12 @@ let `class` = "keyword" or contains nil (no value) to indicate that a value is missing. Nil is roughly equivalent to `null` in other languages. A question mark (?) after the type marks the value as optional of that type. - + If a type is not optional, it is guaranteed to have a value. - + Because Swift requires every property to have a type, even nil must be explicitly stored as an Optional value. - + Optional is an enum, with the cases .none (nil) and .some(T) (the value) */ @@ -178,7 +178,7 @@ let someOptionalString4 = String?.none //nil To access the value of an optional that has a value, use the postfix operator !, which force-unwraps it. Force-unwrapping is like saying, "I know that this optional definitely has a value, please give it to me." - + Trying to use ! to access a non-existent optional value triggers a runtime error. Always make sure that an optional contains a non-nil value before using ! to force-unwrap its value. @@ -194,7 +194,7 @@ if someOptionalString != nil { // Swift supports "optional chaining," which means that you can call functions // or get properties of optional values and they are optionals of the appropriate type. // You can even do this multiple times, hence the name "chaining." - + let empty = someOptionalString?.isEmpty // Bool? // if-let structure - @@ -370,7 +370,7 @@ func say(_ message: String) { } say("Hello") -// Default parameters can be ommitted when calling the function. +// Default parameters can be omitted when calling the function. func printParameters(requiredParameter r: Int, optionalParameter o: Int = 10) { print("The required parameter was \(r) and the optional parameter was \(o)") } @@ -443,7 +443,7 @@ func testGuard() { return // guard statements MUST exit the scope that they are in. // They generally use `return` or `throw`. } - + print("number is \(aNumber)") } testGuard() @@ -564,7 +564,7 @@ enum Furniture { case desk(height: Int) // Associate with String and Int case chair(String, Int) - + func description() -> String { //either placement of let is acceptable switch self { @@ -591,15 +591,15 @@ print(chair.description()) // "Chair of Foo with 40 cm" - Define initializers to set up their initial state - Be extended to expand their functionality beyond a default implementation - Conform to protocols to provide standard functionality of a certain kind - + Classes have additional capabilities that structures don't have: - Inheritance enables one class to inherit the characteristics of another. - Type casting enables you to check and interpret the type of a class instance at runtime. - Deinitializers enable an instance of a class to free up any resources it has assigned. - Reference counting allows more than one reference to a class instance. - + Unless you need to use a class for one of these reasons, use a struct. - + Structures are value types, while classes are reference types. */ @@ -607,7 +607,7 @@ print(chair.description()) // "Chair of Foo with 40 cm" struct NamesTable { let names: [String] - + // Custom subscript subscript(index: Int) -> String { return names[index] @@ -629,7 +629,7 @@ class Shape { class Rect: Shape { var sideLength: Int = 1 - + // Custom getter and setter property var perimeter: Int { get { @@ -640,16 +640,16 @@ class Rect: Shape { sideLength = newValue / 4 } } - + // Computed properties must be declared as `var`, you know, cause' they can change var smallestSideLength: Int { return self.sideLength - 1 } - + // Lazily load a property // subShape remains nil (uninitialized) until getter called lazy var subShape = Rect(sideLength: 4) - + // If you don't need a custom getter and setter, // but still want to run code before and after getting or setting // a property, you can use `willSet` and `didSet` @@ -659,19 +659,19 @@ class Rect: Shape { print(someIdentifier) } } - + init(sideLength: Int) { self.sideLength = sideLength // always super.init last when init custom properties super.init() } - + func shrink() { if sideLength > 0 { sideLength -= 1 } } - + override func getArea() -> Int { return sideLength * sideLength } @@ -703,13 +703,13 @@ class Circle: Shape { override func getArea() -> Int { return 3 * radius * radius } - + // Place a question mark postfix after `init` is an optional init // which can return nil init?(radius: Int) { self.radius = radius super.init() - + if radius <= 0 { return nil } @@ -813,7 +813,7 @@ for _ in 0..<10 { - Internal: Accessible and subclassible in the module it is declared in. - Fileprivate: Accessible and subclassible in the file it is declared in. - Private: Accessible and subclassible in the enclosing declaration (think inner classes/structs/enums) - + See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html */ @@ -878,11 +878,11 @@ extension Int { var doubled: Int { return self * 2 } - + func multipliedBy(num: Int) -> Int { return num * self } - + mutating func multiplyBy(num: Int) { self *= num } @@ -965,18 +965,18 @@ func fakeFetch(value: Int) throws -> String { guard 7 == value else { throw MyError.reallyBadValue(msg: "Some really bad value") } - + return "test" } func testTryStuff() { // assumes there will be no error thrown, otherwise a runtime exception is raised let _ = try! fakeFetch(value: 7) - + // if an error is thrown, then it proceeds, but if the value is nil // it also wraps every return value in an optional, even if its already optional let _ = try? fakeFetch(value: 7) - + do { // normal try operation that provides error handling via `catch` block try fakeFetch(value: 1) -- cgit v1.2.3 From 9c18774c349cbb0821f59f77c6fff3908139bff7 Mon Sep 17 00:00:00 2001 From: hamidra Date: Fri, 1 Nov 2019 20:49:53 -0700 Subject: add downcast to the tutorial --- swift.html.markdown | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 1f9fe897..8582131a 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -692,6 +692,11 @@ print(mySquare.sideLength) // 4 // cast instance let aShape = mySquare as Shape +// downcast instance: +// Because downcasting can fail, the result can be an optional (as?) or an implicitly unwrpped optional (as!). +let anOptionalSquare = aShape as? Square // This will return nil if aShape is not a Square +let aSquare = aShape as! Square // This will throw a runtime error if aShape is not a Square + // compare instances, not the same as == which compares objects (equal to) if mySquare === mySquare { print("Yep, it's mySquare") -- cgit v1.2.3 From 88795664c5ff1980f41bfa39f853cef12f60e92e Mon Sep 17 00:00:00 2001 From: Cory Forsyth Date: Mon, 2 Dec 2019 16:57:13 -0500 Subject: Return value of `findIndex` is `Optional` --- swift.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 1f9fe897..8c1a7755 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -904,7 +904,7 @@ func findIndex(array: [T], valueToFind: T) -> Int? { } return nil } -findIndex(array: [1, 2, 3, 4], valueToFind: 3) // 2 +findIndex(array: [1, 2, 3, 4], valueToFind: 3) // Optional(2) // You can extend types with generics as well extension Array where Array.Element == Int { -- cgit v1.2.3 From 8a54e8b738ab32f5e968e39929a0bd86e0d78aa2 Mon Sep 17 00:00:00 2001 From: mofarajmandi Date: Sat, 17 Oct 2020 16:19:26 -0300 Subject: Add a short note about `final` keyword It's a general good practice to mark classes as `final` unless they are designed to be subclassed. --- swift.html.markdown | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'swift.html.markdown') diff --git a/swift.html.markdown b/swift.html.markdown index 689c5191..3981a4ce 100644 --- a/swift.html.markdown +++ b/swift.html.markdown @@ -822,6 +822,17 @@ for _ in 0..<10 { See more here: https://docs.swift.org/swift-book/LanguageGuide/AccessControl.html */ +// MARK: Preventing Overrides + +// You can add keyword `final` before a class or instance method, or a property to prevent it from being overridden +class Shape { + final var finalInteger = 10 +} + +// Prevent a class from being subclassed +final class ViewManager { +} + // MARK: Conditional Compilation, Compile-Time Diagnostics, & Availability Conditions // Conditional Compilation -- cgit v1.2.3