Social Media hyperlink(URL) copy&paste metadata

To be specific on what is shown in social media when you copy&paste a link from you web application or SharePoint application you have to define HTML headers meta-tags. Most social medias such as Facebook, Twitter, Google+ and LinkedIn support the Open Graph Protocol. It is rather straight forward on to use it. Check our the web site:

http://ogp.me/

For C# developers you can use the HtmlMeta class to perform your needs: HtmlMeta Class

Or you could use a combination of HTML and embbeded code

 

Swift Language Code Refence

Hi,

I started this summer to learn Apples new Swift programming language and on the way I decided to make a slimmed down version of the Apple Swift Language Guide.

You can download it as a PDF(Swift Language Code Reference) or look check it out below. It might be useful to someone. The idea is to see how things work by simple looking at the code.

 

The Basics

 

Constants and Variables

Declaring Constants and Variables

  • let maximumNumberOfLoginAttempts = 10
  • var currentLoginAttempt = 0

 

  • var x = 0, y = 0.0, z = 0.0

 

Type Annotations

  • var welcomeMessage: String

welcomeMessage = “Hello”

  • var red, green, blue: Double

 

Naming Constants and Variables

  • let π = 14159
  • let 你好 = “你好世界”
  • let 🐶🐮 = “dogcow”

 

  • var friendlyWelcome = “Hello!”
  • friendlyWelcome = “Bonjour!”
  • // friendlyWelcome is now “Bonjour!”

 

  • let languageName = “Swift”
  • languageName = “Swift++”
  • // this is a compile-time error – languageName cannot be changed

 

Printing Constants and Variables

  • println(friendlyWelcome)
  • // prints “Bonjour!”

 

  • println(“This is a string”)
  • // prints “This is a string”

 

  • println(“The current value of friendlyWelcome is \(friendlyWelcome)”)
  • // prints “The current value of friendlyWelcome is Bonjour!”

 

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 = “🐱”; println(cat)
  • // prints “🐱”

Integers

Integers are whole numbers with no fractional component, such as 42 and -23. Integers are either signed(positive, zero, or negative) or unsigned (positive or zero).

Swift provides signed and unsigned integers in 8, 16, 32, and 64 bit forms. These integers follow a naming convention similar to C, in that an 8-bit unsigned integer is of type UInt8, and a 32-bit signed integer is of type Int32. Like all types in Swift, these integer types have capitalized names.

 

Integer Bounds

  • let minValue = UInt8.min // minValue is equal to 0, and is of type UInt8
  • let maxValue = UInt8.max // maxValue is equal to 255, and is of type UInt8

 

Int, UInt, Double, Float

 

Type Safety and Type Inference

  • let meaningOfLife = 42
  • // meaningOfLife is inferred to be of type Int

 

  • let pi = 14159
  • // pi is inferred to be of type Double

 

  • let anotherPi = 3 + 14159
  • // anotherPi is also inferred to be of type Double

 

 

Numeric Literals

  • let decimalInteger = 17
  • let binaryInteger = 0b10001 // 17 in binary notation
  • let octalInteger = 0o21 // 17 in octal notation
  • let hexadecimalInteger = 0x11 // 17 in hexadecimal notation

 

  • let decimalDouble = 1875
  • let exponentDouble = 21875e1
  • let hexadecimalDouble = 3p0

 

  • let paddedDouble = 456
  • let oneMillion = 1_000_000
  • let justOverOneMillion = 000_000_1

 

Numeric Type Conversion

Integer Conversion

  • let cannotBeNegative: UInt8 = -1
  • // UInt8 cannot store negative numbers, and so this will report an error
  • let tooBig: Int8 = Int8.max + 1
  • // Int8 cannot store a number larger than its maximum value,
  • // and so this will also report an error

 

  • let twoThousand: UInt16 = 2_000
  • let one: UInt8 = 1
  • let twoThousandAndOne = twoThousand + UInt16(one)

 

Integer and Floating-Point Conversion

 

  • let three = 3
  • let pointOneFourOneFiveNine = 14159
  • let pi = Double(three) + pointOneFourOneFiveNine
  • // pi equals 3.14159, and is inferred to be of type Double

 

  • let integerPi = Int(pi)
  • // integerPi equals 3, and is inferred to be of type Int

 

Type Aliases

  • typealias AudioSample = UInt16
  • let orangesAreOrange = true
  • let turnipsAreDelicious = false
  • var maxAmplitudeFound = AudioSample.min
  • // maxAmplitudeFound is now 0

Booleans

 

  • if turnipsAreDelicious {
  • println(“Mmm, tasty turnips!”)
  • } else {
  • println(“Eww, turnips are horrible.”)
  • }
  • // prints “Eww, turnips are horrible.”

 

  • let i = 1
  • if i {
  • // this example will not compile, and will report an error
  • }

 

  • let i = 1
  • if i == 1 {
  • // this example will compile successfully
  • }

 

Tuples

  • let http404Error = (404, “Not Found”)
  • // http404Error is of type (Int, String), and equals (404, “Not Found”)

 

  • let (statusCode, statusMessage) = http404Error
  • println(“The status code is \(statusCode)”)
  • // prints “The status code is 404″
  • println(“The status message is \(statusMessage)”)
  • // prints “The status message is Not Found”

 

  • let (justTheStatusCode, _) = http404Error
  • println(“The status code is \(justTheStatusCode)”)
  • // prints “The status code is 404″

 

  • println(“The status code is \(http404Error.0)”)
  • // prints “The status code is 404″
  • println(“The status message is \(http404Error.1)”)
  • // prints “The status message is Not Found”

 

  • let http200Status = (statusCode: 200, description: “OK”)

 

  • println(“The status code is \(http200Status.statusCode)”)
  • // prints “The status code is 200″
  • println(“The status message is \(http200Status.description)”)
  • // prints “The status message is OK”

 

Optionals

  • let possibleNumber = “123”
  • let convertedNumber = possibleNumber.toInt()
  • // convertedNumber is inferred to be of type “Int?”, or “optional Int”

 

nil

  • var serverResponseCode: Int? = 404
  • // serverResponseCode contains an actual Int value of 404
  • serverResponseCode = nil
  • // serverResponseCode now contains no value

 

  • var surveyAnswer: String?
  • // surveyAnswer is automatically set to nil

 

If Statements and Forced Unwrapping

  • if convertedNumber != nil {
  • println(“convertedNumber contains some integer value.”)
  • }
  • // prints “convertedNumber contains some integer value.”

 

  • if convertedNumber != nil {
  • println(“convertedNumber has an integer value of \(convertedNumber!).”)
  • }
  • // prints “convertedNumber has an integer value of 123.”

 

Optional Binding

  • if let constantName = someOptional {
  • statements
  • }

 

 

  • if let actualNumber = possibleNumber.toInt() {
  • println(“\(possibleNumber) has an integer value of \(actualNumber)”)
  • } else {
  • println(“\(possibleNumber) could not be converted to an integer”)
  • }
  • // prints “123 has an integer value of 123″

 

Implicitly Unwrapped Optionals

  • let possibleString: String? = “An optional string.”
  • println(possibleString!) // requires an exclamation mark to access its value
  • // prints “An optional string.”
  • let assumedString: String! = “An implicitly unwrapped optional string.”
  • println(assumedString) // no exclamation mark is needed to access its value
  • // prints “An implicitly unwrapped optional string.”

 

  • if assumedString != nil {
  • println(assumedString)
  • }
  • // prints “An implicitly unwrapped optional string.”

 

  • if let definiteString = assumedString {
  • println(definiteString)
  • }
  • // prints “An implicitly unwrapped optional string.”

 

Assertions

Debugging with Assertions

  • let age = -3
  • assert(age >= 0, “A person’s age cannot be less than zero”)
  • // this causes the assertion to trigger, because age is not >= 0

 

  • assert(age >= 0)

 

Basic Operators

Terminology

Operators are unary, binary, or ternary:

  • Unaryoperators operate on a single target (such as -a). Unary prefix operators appear immediately before their target (such as !b), and unary postfix operators appear immediately after their target (such as i++).
  • Binaryoperators operate on two targets (such as 2 + 3) and are infix because they appear in between their two targets.
  • Ternaryoperators operate on three targets. Like C, Swift has only one ternary operator, the ternary conditional operator (a ? b : c).
  • letb = 10
  • vara = 5
  • a = b
  • // a is now equal to 10
  • let (x, y) = (1, 2)
  • // x is equal to 1, and y is equal to 2

Assignment Operator

 

  • ifx = y {
  • // this is not valid, because x = y does not return a value
  • }

 

Arithmetic Operators

Swift supports the four standard arithmetic operators for all number types:

  • Addition (+)
  • Subtraction (-)
  • Multiplication (*)
  • Division (/)
  • 1 + 2// equals 3
  • 5 – 3// equals 2
  • 2 * 3// equals 6
  • 0 / 2.5// equals 4.0
  • “hello, ” + “world”// equals “hello, world”

 

  • letdog: Character = “🐶”
  • letcow: Character = “🐮”
  • letdogCow = dog + cow
  • // dogCow is equal to “🐶🐮”
  • 9 % 4// equals 1
  • -9 % 4 // equals -1
  • 8 % 5// equals 0.5
  • vari = 0
  • ++i// i now equals 1

Remainder Operator

Floating-Point Remainder Calculations

Increment and Decrement Operators

 

  • If the operator is writtenbefore the variable, it increments the variable before returning its value.
  • If the operator is writtenafter the variable, it increments the variable after returning its value.

 

For example:

  • vara = 0
  • letb = ++a
  • // a and b are now both equal to 1
  • letc = a++
  • // a is now equal to 2, but c has been set to the pre-increment value of 1

 

Unary Minus Operator

  • letthree = 3
  • letminusThree = -three// minusThree equals -3
  • letplusThree = -minusThree// plusThree equals 3, or “minus minus three”
  • letminusSix = -6
  • letalsoMinusSix = +minusSix// alsoMinusSix equals -6
  • vara = 1
  • a += 2
  • // a is now equal to 3

Unary Plus Operator

Compound Assignment Operators

Comparison Operators

Swift supports all standard C comparison operators:

  • Equal to (a == b)
  • Not equal to (a != b)
  • Greater than (a > b)
  • Less than (a < b)
  • Greater than or equal to (a >= b)
  • Less than or equal to (a <= b)

NOTE

  • 1 == 1// true, because 1 is equal to 1
  • 2 != 1// true, because 2 is not equal to 1
  • 2 > 1// true, because 2 is greater than 1
  • 1 < 2// true, because 1 is less than 2
  • 1 >= 1// true, because 1 is greater than or equal to 1
  • 2 <= 1// false, because 2 is not less than or equal to 1

 

  • letname = “world”
  • ifname == “world” {
  • println(“hello, world”)
  • } else {
  • println(“I’m sorry \(name), but I don’t recognize you”)
  • }
  • // prints “hello, world”, because name is indeed equal to “world”
  • ifquestion {
  • answer1
  • } else {
  • answer2
  • }

Ternary Conditional Operator

 

  • letcontentHeight = 40
  • lethasHeader = true
  • letrowHeight = contentHeight + (hasHeader ? 50 : 20)
  • // rowHeight is equal to 90

The preceding example is shorthand for the code below:

  • letcontentHeight = 40
  • lethasHeader = true
  • varrowHeight = contentHeight
  • ifhasHeader {
  • rowHeight = rowHeight + 50
  • } else {
  • rowHeight = rowHeight + 20
  • }
  • // rowHeight is equal to 90

 

Nil Coalescing Operator

 

  • a != nil ? a! : b

 

  • letdefaultColorName = “red”
  • varuserDefinedColorName: String? // defaults to nil
  • varcolorNameToUse = userDefinedColorName ?? defaultColorName
  • // userDefinedColorName is nil, so colorNameToUse is set to the default of “red”

 

  • userDefinedColorName = “green”
  • colorNameToUse = userDefinedColorName ?? defaultColorName
  • // userDefinedColorName is not nil, so colorNameToUse is set to “green”
  • forindexin1…5 {
  • println(“\(index) times 5 is \(index * 5)”)
  • }
  • // 1 times 5 is 5
  • // 2 times 5 is 10
  • // 3 times 5 is 15
  • // 4 times 5 is 20
  • // 5 times 5 is 25
  • letnames = ["Anna", "Alex", "Brian", "Jack"]
  • letcount = names.count
  • foriin0..<count {
  • println(“Person \(i + 1) is called \(names[i])”)
  • }
  • // Person 1 is called Anna
  • // Person 2 is called Alex
  • // Person 3 is called Brian
  • // Person 4 is called Jack
  • Logical NOT (!a)
  • Logical AND (a && b)
  • Logical OR (a || b)
  • letallowedEntry = false
  • if !allowedEntry {
  • println(“ACCESS DENIED”)
  • }
  • // prints “ACCESS DENIED”
  • letenteredDoorCode = true
  • letpassedRetinaScan = false
  • ifenteredDoorCode && passedRetinaScan {
  • println(“Welcome!”)
  • } else {
  • println(“ACCESS DENIED”)
  • }
  • // prints “ACCESS DENIED”
  • lethasDoorKey = false
  • letknowsOverridePassword = true
  • ifhasDoorKey || knowsOverridePassword {
  • println(“Welcome!”)
  • } else {
  • println(“ACCESS DENIED”)
  • }
  • // prints “Welcome!”
  • ifenteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
  • println(“Welcome!”)
  • } else {
  • println(“ACCESS DENIED”)
  • }
  • // prints “Welcome!”
  • if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
  • println(“Welcome!”)
  • } else {
  • println(“ACCESS DENIED”)
  • }
  • // prints “Welcome!”

Range Operators

Closed Range Operator

Half-Open Range Operator

Logical Operators

Logical NOT Operator

Logical AND Operator

Logical OR Operator

Combining Logical Operators

Explicit Parentheses

 

Strings and Characters

String Literals

  • letsomeString = “Some string literal value”
  • varemptyString = “”// empty string literal
  • varanotherEmptyString = String() // initializer syntax
  • // these two strings are both empty, and are equivalent to each other

Initializing an Empty String

 

  • ifemptyString.isEmpty {
  • println(“Nothing to see here”)
  • }
  • // prints “Nothing to see here”
  • varvariableString = “Horse”
  • variableString += ” and carriage”
  • // variableString is now “Horse and carriage”

String Mutability

 

  • letconstantString = “Highlander”
  • constantString += ” and another Highlander”
  • // this reports a compile-time error – a constant string cannot be modified
  • forcharacterin”Dog!🐶” {
  • println(character)
  • }
  • // D
  • // o
  • // g
  • // !
  • // 🐶
  • letyenSign: Character = “¥”
  • letstring1 = “hello”
  • letstring2 = ” there”
  • letcharacter1: Character = “!”
  • letcharacter2: Character = “?”

Working with Characters

Concatenating Strings and Characters

 

  • letstringPlusCharacter = string1 + character1// equals “hello!”
  • letstringPlusString = string1 + string2// equals “hello there”
  • letcharacterPlusString = character1 + string1// equals “!hello”
  • letcharacterPlusCharacter = character1 + character2// equals “!?”

 

  • varinstruction = “look over”
  • instruction += string2
  • // instruction now equals “look over there”

 

  • varwelcome = “good morning”
  • welcome += character1
  • // welcome now equals “good morning!”
  • letmultiplier = 3
  • letmessage = “\(multiplier) times 2.5 is \(Double(multiplier) * 5)”
  • // message is “3 times 2.5 is 7.5″

 

String Interpolation

 

Unicode

.

Unicode Scalars

Special Unicode Characters in String Literals

String literals can include the following special Unicode characters:

  • The escaped special characters (null character), \\ (backslash), \t (horizontal tab), \n (line feed),\r (carriage return), \” (double quote) and \’ (single quote)
  • An arbitrary Unicode scalar, written as\u{n}, where n is between one and eight hexadecimal digits

 

  • letwiseWords = “\”Imagination is more important than knowledge\” – Einstein”
  • // “Imagination is more important than knowledge” – Einstein
  • letdollarSign = “\u{24}”// $, Unicode scalar U+0024
  • letblackHeart = “\u{2665}”// ♥, Unicode scalar U+2665
  • letsparklingHeart = “\u{1F496}”// 💖, Unicode scalar U+1F496

Extended Grapheme Clusters

 

  • leteAcute: Character = “\u{E9}”// é
  • letcombinedEAcute: Character = “\u{65}\u{301}”// e followed by ́
  • // eAcute is é, combinedEAcute is é

 

  • letprecomposed: Character = “\u{D55C}”// 한
  • letdecomposed: Character = “\u{1112}\u{1161}\u{11AB}”// ᄒ, ᅡ, ᆫ
  • // precomposed is 한, decomposed is 한

 

  • letenclosedEAcute: Character = “\u{E9}\u{20DD}”
  • // enclosedEAcute is é⃝

 

  • letregionalIndicatorForUS: Character = “\u{1F1FA}\u{1F1F8}”
  • // regionalIndicatorForUS is 🇺🇸
  • letunusualMenagerie = “Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪”
  • println(“unusualMenagerie has \(countElements(unusualMenagerie)) characters”)
  • // prints “unusualMenagerie has 40 characters”

Counting Characters

 

  • varword = “cafe”
  • println(“the number of characters in \(word) is \(countElements(word))”)
  • // prints “the number of characters in cafe is 4″

 

  • word += “\u{301}”// COMBINING ACUTE ACCENT, U+0301

 

  • println(“the number of characters in \(word) is \(countElements(word))”)
  • // prints “the number of characters in café is 4″

Comparing Strings

Swift provides three ways to compare textual values: string and character equality, prefix equality, and suffix equality.

String and Character Equality

  • letquotation = “We’re a lot alike, you and I.”
  • letsameQuotation = “We’re a lot alike, you and I.”
  • ifquotation == sameQuotation {
  • println(“These two strings are considered equal”)
  • }
  • // prints “These two strings are considered

 

  • // “Voulez-vous un café?” using LATIN SMALL LETTER E WITH ACUTE
  • leteAcuteQuestion = “Voulez-vous un caf\u{E9}?”

 

  • // “Voulez-vous un café?” using LATIN SMALL LETTER E and COMBINING ACUTE ACCENT
  • letcombinedEAcuteQuestion = “Voulez-vous un caf\u{65}\u{301}?”

 

  • ifeAcuteQuestion == combinedEAcuteQuestion {
  • println(“These two strings are considered equal”)
  • }
  • // prints “These two strings are considered equal”

 

  • letlatinCapitalLetterA: Character = “\u{41}”
  • letcyrillicCapitalLetterA: Character = “\u{0410}”

 

  • iflatinCapitalLetterA != cyrillicCapitalLetterA {
  • println(“These two characters are not equivalent”)
  • }
  • // prints “These two characters are not equivalent”

String and character comparisons in Swift are not locale-sensitive.

Prefix and Suffix Equality

  • letromeoAndJuliet = [
  • "Act 1 Scene 1: Verona, A public place",
  • "Act 1 Scene 2: Capulet's mansion",
  • "Act 1 Scene 3: A room in Capulet's mansion",
  • "Act 1 Scene 4: A street outside Capulet's mansion",
  • "Act 1 Scene 5: The Great Hall in Capulet's mansion",
  • "Act 2 Scene 1: Outside Capulet's mansion",
  • "Act 2 Scene 2: Capulet's orchard",
  • "Act 2 Scene 3: Outside Friar Lawrence's cell",
  • "Act 2 Scene 4: A street in Verona",
  • "Act 2 Scene 5: Capulet's mansion",
  • "Act 2 Scene 6: Friar Lawrence's cell"
  • ]

 

  • varact1SceneCount = 0
  • forsceneinromeoAndJuliet {
  • ifscene.hasPrefix(“Act 1 “) {
  • ++act1SceneCount
  • }
  • }
  • println(“There are \(act1SceneCount) scenes in Act 1″)
  • // prints “There are 5 scenes in Act 1″

 

  • varmansionCount = 0
  • varcellCount = 0
  • forsceneinromeoAndJuliet {
  • ifscene.hasSuffix(“Capulet’s mansion”) {
  • ++mansionCount
  • } else if scene.hasSuffix(“Friar Lawrence’s cell”) {
  • ++cellCount
  • }
  • }
  • println(“\(mansionCount) mansion scenes; \(cellCount) cell scenes”)
  • // prints “6 mansion scenes; 2 cell scenes”

 

Unicode Representations of Strings

  • letdogString = “Dog‼🐶”
  • forcodeUnitindogString.utf8 {
  • print(“\(codeUnit) “)
  • }
  • print(“\n”)
  • // 68 111 103 226 128 188 240 159 144 182
  • forcodeUnitindogString.utf16 {
  • print(“\(codeUnit) “)
  • }
  • print(“\n”)
  • // 68 111 103 8252 55357 56374
  • forscalarindogString.unicodeScalars {
  • print(“\(scalar.value) “)
  • }
  • print(“\n”)
  • // 68 111 103 8252 128054

UTF-8 Representation

 

UTF-16 Representation

Unicode Scalar Representation

 

  • forscalarindogString.unicodeScalars {
  • println(“\(scalar) “)
  • }
  • // D
  • // o
  • // g
  • // ‼
  • // 🐶

 

Collection Types

 

Swift provides two collection types, known as arrays and dictionaries, for storing collections of values. Arrays store ordered lists of values of the same type. Dictionaries store unordered collections of values of the same type, which can be referenced and looked up through a unique identifier (also known as a key).

Arrays and dictionaries in Swift are always clear about the types of values and keys that they can store. This means that you cannot insert a value of the wrong type into an array or dictionary by mistake. It also means you can be confident about the types of values you will retrieve from an array or dictionary. Swift’s use of explicitly typed collections ensures that your code is always clear about the types of values it can work with and enables you to catch any type mismatches early in your code’s development.

Behind the scenes, Swift’s array and dictionary types are implemented as generic collections. For more on generic types and collections.

Mutability of Collections

If you create an array or a dictionary and assign it to a variable, the collection that is created will be mutable. This means that you can change (or mutate) the collection after it is created by adding, removing, or changing items in the collection. Conversely, if you assign an array or a dictionary to a constant, that array or dictionary is immutable, and its size and contents cannot be changed.

NOTE

It is good practice to create immutable collections in all cases where the collection does not need to change. Doing so enables the Swift compiler to optimize the performance of the collections you create.

Arrays

 

Array Type Shorthand Syntax

The type of a Swift array is written in full as Array<SomeType>, where SomeType is the type that the array is allowed to store. You can also write the type of an array in shorthand form as [SomeType]. Although the two forms are functionally identical, the shorthand form is preferred, and is used throughout this guide when referring to the type of an array.

Array Literals

·          [value 1, value 2, value 3]

  • varshoppingList: [String] = ["Eggs", "Milk"]
  • // shoppingList has been initialized with two initial items
  • varshoppingList = ["Eggs", "Milk"]

 

Accessing and Modifying an Array

  • println(“The shopping list contains \(shoppingList.count)”)
  • // prints “The shopping list contains 2 items.”

 

  • ifshoppingList.isEmpty {
  • println(“The shopping list is empty.”)
  • } else {
  • println(“The shopping list is not empty.”)
  • }
  • // prints “The shopping list is not empty.”

 

  • shoppingList.append(“Flour”)
  • // shoppingList now contains 3 items, and someone is making pancakes

 

  • shoppingList += ["Baking Powder"]
  • // shoppingList now contains 4 items
  • shoppingList += ["Chocolate Spread", "Cheese", "Butter"]
  • // shoppingList now contains 7 items

 

  • varfirstItem = shoppingList[0]
  • // firstItem is equal to “Eggs”

 

  • shoppingList[0] = “Six eggs”
  • // the first item in the list is now equal to “Six eggs” rather than “Eggs”

 

  • shoppingList[4...6] = ["Bananas", "Apples"]
  • // shoppingList now contains 6 items

 

  • shoppingList.insert(“Maple Syrup”, atIndex: 0)
  • // shoppingList now contains 7 items
  • // “Maple Syrup” is now the first item in the list

 

  • letmapleSyrup = shoppingList.removeAtIndex(0)
  • // the item that was at index 0 has just been removed
  • // shoppingList now contains 6 items, and no Maple Syrup
  • // the mapleSyrup constant is now equal to the removed “Maple Syrup” string

 

  • firstItem = shoppingList[0]
  • // firstItem is now equal to “Six eggs”

 

  • letapples = shoppingList.removeLast()
  • // the last item in the array has just been removed
  • // shoppingList now contains 5 items, and no apples
  • // the apples constant is now equal to the removed “Apples” string
  • foriteminshoppingList {
  • println(item)
  • }
  • // Six eggs
  • // Milk
  • // Flour
  • // Baking Powder
  • // Bananas

Iterating Over an Array

 

  • for (index, value) inenumerate(shoppingList) {
  • println(“Item \(index + 1): \(value)”)
  • }
  • // Item 1: Six eggs
  • // Item 2: Milk
  • // Item 3: Flour
  • // Item 4: Baking Powder
  • // Item 5: Bananas
  • varsomeInts = [Int]()
  • println(“someInts is of type [Int] with \(someInts.count)”)
  • // prints “someInts is of type [Int] with 0 items.”

Creating and Initializing an Array

 

  • someInts.append(3)
  • // someInts now contains 1 value of type Int
  • someInts = []
  • // someInts is now an empty array, but is still of type [Int]
  • varthreeDoubles = [Double](count: 3, repeatedValue: 0)
  • // threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]

 

  • varanotherThreeDoubles = [Double](count: 3, repeatedValue: 5)
  • // anotherThreeDoubles is inferred as [Double], and equals [2.5, 2.5, 2.5]

 

  • varsixDoubles = threeDoubles + anotherThreeDoubles
  • // sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

Dictionaries

Dictionary Type Shorthand Syntax

The type of a Swift dictionary is written in full as Dictionary<KeyType, ValueType>, where KeyType is the type of value that can be used as a dictionary key, and ValueType is the type of value that the dictionary stores for those keys.

You can also write the type of a dictionary in shorthand form as [KeyType: ValueType]. Although the two forms are functionally identical, the shorthand form is preferred, and is used throughout this guide when referring to the type of a dictionary.

Dictionary Literals

·          [key 1: value 1, key 2: value 2, key 3: value 3]

  • varairports: [String: String] = ["TYO": "Tokyo", "DUB": "Dublin"]
  • varairports = ["TYO": "Tokyo", "DUB": "Dublin"]
  • println(“The airports dictionary contains \(airports.count)”)
  • // prints “The airports dictionary contains 2 items.”

Accessing and Modifying a Dictionary

 

  • ifairports.isEmpty {
  • println(“The airports dictionary is empty.”)
  • } else {
  • println(“The airports dictionary is not empty.”)
  • }
  • // prints “The airports dictionary is not empty.”

 

  • airports["LHR"] = “London”
  • // the airports dictionary now contains 3 items

 

  • airports["LHR"] = “London Heathrow”
  • // the value for “LHR” has been changed to “London Heathrow”

 

  • ifletoldValue = airports.updateValue(“Dublin International”, forKey: “DUB”) {
  • println(“The old value for DUB was \(oldValue).”)
  • }
  • // prints “The old value for DUB was Dublin.”

 

  • ifletairportName = airports["DUB"] {
  • println(“The name of the airport is \(airportName).”)
  • } else {
  • println(“That airport is not in the airports dictionary.”)
  • }
  • // prints “The name of the airport is Dublin International.”

 

  • airports["APL"] = “Apple International”
  • // “Apple International” is not the real airport for APL, so delete it
  • airports["APL"] = nil
  • // APL has now been removed from the dictionary

 

  • ifletremovedValue = airports.removeValueForKey(“DUB”) {
  • println(“The removed airport’s name is \(removedValue).”)
  • } else {
  • println(“The airports dictionary does not contain a value for DUB.”)
  • }
  • // prints “The removed airport’s name is Dublin International.”
  • for (airportCode, airportName) inairports {
  • println(“\(airportCode): \(airportName)”)
  • }
  • // LHR: London Heathrow
  • // TYO: Tokyo

Iterating Over a Dictionary

 

  • forairportCodeinairports.keys {
  • println(“Airport code: \(airportCode)”)
  • }
  • // Airport code: LHR
  • // Airport code: TYO
  • forairportNameinairports.values {
  • println(“Airport name: \(airportName)”)
  • }
  • // Airport name: London Heathrow
  • // Airport name: Tokyo

 

  • letairportCodes = [String](airports.keys)
  • // airportCodes is ["LHR", "TYO"]
  • letairportNames = [String](airports.values)
  • // airportNames is ["London Heathrow", "Tokyo"]
  • varnamesOfIntegers = [Int: String]()
  • // namesOfIntegers is an empty [Int: String] dictionary

Creating an Empty Dictionary

 

  • namesOfIntegers[16] = “sixteen”
  • // namesOfIntegers now contains 1 key-value pair
  • namesOfIntegers = [:]
  • // namesOfIntegers is once again an empty dictionary of type [Int: String]

Hash Values for Dictionary Key Types

A type must be hashable in order to be used as a dictionary’s key type—that is, the type must provide a way to compute a hash value for itself. A hash value is an Int value that is the same for all objects that compare equal, such that if a == b, it follows that a.hashValue == b.hashValue.

 

Control Flow

For Loops

A for loop performs a set of statements a certain number of times. Swift provides two kinds of for loop:

  • for-inperforms a set of statements for each item in a range, sequence, collection, or progression.
  • for-condition-incrementperforms a set of statements until a specific condition is met, typically by incrementing a counter each time the loop ends.
  • forindexin1…5 {
  • println(“\(index) times 5 is \(index * 5)”)
  • }
  • // 1 times 5 is 5
  • // 2 times 5 is 10
  • // 3 times 5 is 15
  • // 4 times 5 is 20
  • // 5 times 5 is 25

For-In

 

  • letbase = 3
  • letpower = 10
  • varanswer = 1
  • for_in1…power {
  • answer *= base
  • }
  • println(“\(base) to the power of \(power) is \(answer)”)
  • // prints “3 to the power of 10 is 59049″

 

  • letnames = ["Anna", "Alex", "Brian", "Jack"]
  • fornameinnames {
  • println(“Hello, \(name)!”)
  • }
  • // Hello, Anna!
  • // Hello, Alex!
  • // Hello, Brian!
  • // Hello, Jack!

 

  • letnumberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
  • for (animalName, legCount) innumberOfLegs {
  • println(“\(animalName)s have \(legCount) legs”)
  • }
  • // spiders have 8 legs
  • // cats have 4 legs
  • // ants have 6 legs

 

  • forcharacterin”Hello” {
  • println(character)
  • }
  • // H
  • // e
  • // l
  • // l
  • // o
  • forvarindex = 0; index < 3; ++index {
  • println(“index is \(index)”)
  • }
  • // index is 0
  • // index is 1
  • // index is 2

For-Condition-Increment

Here’s the general form of this loop format:

·         for initialization; condition; increment {·             statements·         }

 

The loop format and execution process described above is shorthand for (and equivalent to) the outline below:

·         initialization·         while condition {·             statements·             increment·         }

Constants and variables declared within the initialization expression (such as var index = 0) are only valid within the scope of the for loop itself. To retrieve the final value of index after the loop ends, you must declare index before the loop’s scope begins:

  • varindex: Int
  • forindex = 0; index < 3; ++index {
  • println(“index is \(index)”)
  • }
  • // index is 0
  • // index is 1
  • // index is 2
  • println(“The loop statements were executed \(index) times”)
  • // prints “The loop statements were executed 3 times”

While Loops

Swift provides two kinds ofwhile loop:

  • whileevaluates its condition at the start of each pass through the loop.
  • do-whileevaluates its condition at the end of each pass through the loop.

While

·         while condition {·             statements·         }

This example plays a simple game of Snakes and Ladders (also known as Chutes and Ladders):

 

The rules of the game are as follows:

  • The board has 25 squares, and the aim is to land on or beyond square 25.
  • Each turn, you roll a six-sided dice and move by that number of squares, following the horizontal path indicated by the dotted arrow above.
  • If your turn ends at the bottom of a ladder, you move up that ladder.
  • If your turn ends at the head of a snake, you move down that snake.

 

  • letfinalSquare = 25
  • varboard = [Int](count: finalSquare + 1, repeatedValue: 0)

 

  • board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  • board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08

 

  • varsquare = 0
  • vardiceRoll = 0
  • whilesquare < finalSquare {
  • // roll the dice
  • if ++diceRoll == 7 { diceRoll = 1 }
  • // move by the rolled amount
  • square += diceRoll
  • ifsquare < board.count {
  • // if we’re still on the board, move up or down for a snake or a ladder
  • square += board[square]
  • }
  • }
  • println(“Game over!”)

 

Do-While

·         do {·             statements·         } while condition

 

  • letfinalSquare = 25
  • varboard = [Int](count: finalSquare + 1, repeatedValue: 0)
  • board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  • board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  • varsquare = 0
  • vardiceRoll = 0

 

  • do {
  • // move up or down for a snake or ladder
  • square += board[square]
  • // roll the dice
  • if ++diceRoll == 7 { diceRoll = 1 }
  • // move by the rolled amount
  • square += diceRoll
  • } while square < finalSquare
  • println(“Game over!”)

 

Conditional Statements

If

  • vartemperatureInFahrenheit = 30
  • iftemperatureInFahrenheit <= 32 {
  • println(“It’s very cold. Consider wearing a scarf.”)
  • }
  • // prints “It’s very cold. Consider wearing a scarf.”

 

  • temperatureInFahrenheit = 40
  • iftemperatureInFahrenheit <= 32 {
  • println(“It’s very cold. Consider wearing a scarf.”)
  • } else {
  • println(“It’s not that cold. Wear a t-shirt.”)
  • }
  • // prints “It’s not that cold. Wear a t-shirt.”

 

  • temperatureInFahrenheit = 90
  • iftemperatureInFahrenheit <= 32 {
  • println(“It’s very cold. Consider wearing a scarf.”)
  • } else if temperatureInFahrenheit >= 86 {
  • println(“It’s really warm. Don’t forget to wear sunscreen.”)
  • } else {
  • println(“It’s not that cold. Wear a t-shirt.”)
  • }
  • // prints “It’s really warm. Don’t forget to wear sunscreen.”

 

  • temperatureInFahrenheit = 72
  • iftemperatureInFahrenheit <= 32 {
  • println(“It’s very cold. Consider wearing a scarf.”)
  • } else if temperatureInFahrenheit >= 86 {
  • println(“It’s really warm. Don’t forget to wear sunscreen.”)
  • }

Switch

In its simplest form, a switch statement compares a value against one or more values of the same type:

·         switch some value to consider {·         case value 1:·             respond to value 1·         case value 2,·         value 3:·             respond to value 2 or 3·         default:·             otherwise, do something else·         }

This example uses a switch statement to consider a single lowercase character called someCharacter:

  • letsomeCharacter: Character = “e”
  • switchsomeCharacter {
  • case”a”, “e”, “i”, “o”, “u”:
  • println(“\(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”:
  • println(“\(someCharacter) is a consonant”)
  • default:
  • println(“\(someCharacter) is not a vowel or a consonant”)
  • }
  • // prints “e is a vowel”

No Implicit Fallthrough

It is not valid to write the following code, because the first case is empty:

  • letanotherCharacter: Character = “a”
  • switchanotherCharacter {
  • case”a”:
  • case”A”:
  • println(“The letter A”)
  • default:
  • println(“Not the letter A”)
  • }
  • // this will report a compile-time error

Multiple matches for a single switch case can be separated by commas, and can be written over multiple lines if the list is long:

·         switch some value to consider {·         case value 1,·         value 2:·             statements·         }

Range Matching

Values in switch cases can be checked for their inclusion in a range. This example uses number ranges to provide a natural-language count for numbers of any size:

  • letcount = 3_000_000_000_000
  • letcountedThings = “stars in the Milky Way”
  • varnaturalCount: String
  • switchcount {
  • case0:
  • naturalCount = “no”
  • case1…3:
  • naturalCount = “a few”
  • case4…9:
  • naturalCount = “several”
  • case10…99:
  • naturalCount = “tens of”
  • case100…999:
  • naturalCount = “hundreds of”
  • case1000…999_999:
  • naturalCount = “thousands of”
  • default:
  • naturalCount = “millions and millions of”
  • }
  • println(“There are \(naturalCount) \(countedThings).”)
  • // prints “There are millions and millions of stars in the Milky Way.”
  • letsomePoint = (1, 1)
  • switchsomePoint {
  • case (0, 0):
  • println(“(0, 0) is at the origin”)
  • case (_, 0):
  • println(“(\(somePoint.0), 0) is on the x-axis”)
  • case (0, _):
  • println(“(0, \(somePoint.1)) is on the y-axis”)
  • case (-2…2, -2…2):
  • println(“(\(somePoint.0), \(somePoint.1)) is inside the box”)
  • default:
  • println(“(\(somePoint.0), \(somePoint.1)) is outside of the box”)
  • }
  • // prints “(1, 1) is inside the box”

Tuples

 

Value Bindings

  • letanotherPoint = (2, 0)
  • switchanotherPoint {
  • case (letx, 0):
  • println(“on the x-axis with an x value of \(x)”)
  • case (0, lety):
  • println(“on the y-axis with a y value of \(y)”)
  • caselet (x, y):
  • println(“somewhere else at (\(x), \(y))”)
  • }
  • // prints “on the x-axis with an x value of 2″

 

Where

  • letyetAnotherPoint = (1, -1)
  • switchyetAnotherPoint {
  • caselet (x, y) wherex == y:
  • println(“(\(x), \(y)) is on the line x == y”)
  • caselet (x, y) wherex == -y:
  • println(“(\(x), \(y)) is on the line x == -y”)
  • caselet (x, y):
  • println(“(\(x), \(y)) is just some arbitrary point”)
  • }
  • // prints “(1, -1) is on the line x == -y”

 

Control Transfer Statements

Control transfer statements change the order in which your code is executed, by transferring control from one piece of code to another. Swift has four control transfer statements:

  • continue
  • break
  • fallthrough
  • return
  • letpuzzleInput = “great minds think alike”
  • varpuzzleOutput = “”
  • forcharacterinpuzzleInput {
  • switchcharacter {
  • case”a”, “e”, “i”, “o”, “u”, ” “:
  • continue
  • default:
  • puzzleOutput += character
  • }
  • }
  • println(puzzleOutput)
  • // prints “grtmndsthnklk”

Continue

Break

The break statement ends execution of an entire control flow statement immediately. The break statement can be used inside a switch statement or loop statement when you want to terminate the execution of theswitch or loop statement earlier than would otherwise be the case.

Break in a Loop Statement

When used inside a loop statement, break ends the loop’s execution immediately, and transfers control to the first line of code after the loop’s closing brace (}). No further code from the current iteration of the loop is executed, and no further iterations of the loop are started.

Break in a Switch Statement

When used inside a switch statement, break causes the switch statement to end its execution immediately, and to transfer control to the first line of code after the switch statement’s closing brace (}).

This behavior can be used to match and ignore one or more cases in a switch statement. Because Swift’sswitch statement is exhaustive and does not allow empty cases, it is sometimes necessary to deliberately match and ignore a case in order to make your intentions explicit. You do this by writing the break statement as the entire body of the case you want to ignore. When that case is matched by the switch statement, thebreak statement inside the case ends the switch statement’s execution immediately.

  • letnumberSymbol: Character = “三”// Simplified Chinese for the number 3
  • varpossibleIntegerValue: Int?
  • switchnumberSymbol {
  • case”1″, “١”, “一”, “๑”:
  • possibleIntegerValue = 1
  • case”2″, “٢”, “二”, “๒”:
  • possibleIntegerValue = 2
  • case”3″, “٣”, “三”, “๓”:
  • possibleIntegerValue = 3
  • case”4″, “٤”, “四”, “๔”:
  • possibleIntegerValue = 4
  • default:
  • break
  • }
  • ifletintegerValue = possibleIntegerValue {
  • println(“The integer value of \(numberSymbol) is \(integerValue).”)
  • } else {
  • println(“An integer value could not be found for \(numberSymbol).”)
  • }
  • // prints “The integer value of 三 is 3.”

 

Fallthrough

Switch statements in Swift do not fall through the bottom of each case and into the next one. Instead, the entire switch statement completes its execution as soon as the first matching case is completed. By contrast, C requires you to insert an explicit break statement at the end of every switch case to prevent fallthrough. Avoiding default fallthrough means that Swift switch statements are much more concise and predictable than their counterparts in C, and thus they avoid executing multiple switch cases by mistake.

If you really need C-style fallthrough behavior, you can opt in to this behavior on a case-by-case basis with the fallthrough keyword. The example below uses fallthrough to create a textual description of a number:

  • letintegerToDescribe = 5
  • vardescription = “The number \(integerToDescribe) is”
  • switchintegerToDescribe {
  • case2, 3, 5, 7, 11, 13, 17, 19:
  • description += ” a prime number, and also”
  • fallthrough
  • default:
  • description += ” an integer.”
  • }
  • println(description)
  • // prints “The number 5 is a prime number, and also an integer.”

 

Labeled Statements

A labeled statement is indicated by placing a label on the same line as the statement’s introducer keyword, followed by a colon. Here’s an example of this syntax for a while loop, although the principle is the same for all loops and switch statements:

·         label name: while condition {·             statements·         }

 

  • letfinalSquare = 25
  • varboard = [Int](count: finalSquare + 1, repeatedValue: 0)
  • board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  • board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  • varsquare = 0
  • vardiceRoll = 0

 

  • gameLoop: whilesquare != finalSquare {
  • if ++diceRoll == 7 { diceRoll = 1 }
  • switchsquare + diceRoll {
  • casefinalSquare:
  • // diceRoll will move us to the final square, so the game is over
  • breakgameLoop
  • caseletnewSquarewherenewSquare > finalSquare:
  • // diceRoll will move us beyond the final square, so roll again
  • continuegameLoop
  • default:
  • // this is a valid move, so find out its effect
  • square += diceRoll
  • square += board[square]
  • }
  • }
  • println(“Game over!”)

 

 

Functions

Defining and Calling Functions

  • funcsayHello(personName: String) -> String {
  • letgreeting = “Hello, ” + personName + “!”
  • returngreeting
  • }

 

  • println(sayHello(“Anna”))
  • // prints “Hello, Anna!”
  • println(sayHello(“Brian”))
  • // prints “Hello, Brian!”

 

  • funcsayHelloAgain(personName: String) -> String {
  • return”Hello again, ” + personName + “!”
  • }
  • println(sayHelloAgain(“Anna”))
  • // prints “Hello again, Anna!”
  • funchalfOpenRangeLength(start: Int, end: Int) -> Int {
  • returnend – start
  • }
  • println(halfOpenRangeLength(1, 10))
  • // prints “9”
  • funcsayHelloWorld() -> String {
  • return”hello, world”
  • }
  • println(sayHelloWorld())
  • // prints “hello, world”
  • funcsayGoodbye(personName: String) {
  • println(“Goodbye, \(personName)!”)
  • }
  • sayGoodbye(“Dave”)
  • // prints “Goodbye, Dave!”
  • funcprintAndCount(stringToPrint: String) -> Int {
  • println(stringToPrint)
  • returncountElements(stringToPrint)
  • }
  • funcprintWithoutCounting(stringToPrint: String) {
  • printAndCount(stringToPrint)
  • }
  • printAndCount(“hello, world”)
  • // prints “hello, world” and returns a value of 12
  • printWithoutCounting(“hello, world”)
  • // prints “hello, world” but does not return a value
  • funcminMax(array: [Int]) -> (min: Int, max: Int) {
  • varcurrentMin = array[0]
  • varcurrentMax = array[0]
  • forvalueinarray[1..<array.count] {
  • ifvalue < currentMin {
  • currentMin = value
  • } else if value > currentMax {
  • currentMax = value
  • }
  • }
  • return (currentMin, currentMax)
  • }

Function Parameters and Return Values

Multiple Input Parameters

Functions Without Parameters

Functions Without Return Values

Functions with Multiple Return Values

 

  • letbounds = minMax([8, -6, 2, 109, 3, 71])
  • println(“min is \(bounds.min) and max is \(bounds.max)”)
  • // prints “min is -6 and max is 109″
  • funcminMax(array: [Int]) -> (min: Int, max: Int)? {
  • ifarray.isEmpty { returnnil }
  • varcurrentMin = array[0]
  • varcurrentMax = array[0]
  • forvalueinarray[1..<array.count] {
  • ifvalue < currentMin {
  • currentMin = value
  • } else if value > currentMax {
  • currentMax = value
  • }
  • }
  • return (currentMin, currentMax)
  • }

Optional Tuple Return Types

 

  • ifletbounds = minMax([8, -6, 2, 109, 3, 71]) {
  • println(“min is \(bounds.min) and max is \(bounds.max)”)
  • }
  • // prints “min is -6 and max is 109″

Function Parameter Names

All of the above functions define parameter names for their parameters:

  • funcsomeFunction(parameterName: Int) {
  • // function body goes here, and can use parameterName
  • // to refer to the argument value for that parameter
  • }

However, these parameter names are only used within the body of the function itself, and cannot be used when calling the function. These kinds of parameter names are known as local parameter names, because they are only available for use within the function’s body.

External Parameter Names

Sometimes it’s useful to name each parameter when you call a function, to indicate the purpose of each argument you pass to the function.

If you want users of your function to provide parameter names when they call your function, define anexternal parameter name for each parameter, in addition to the local parameter name. You write an external parameter name before the local parameter name it supports, separated by a space:

  • funcsomeFunction(externalParameterNamelocalParameterName: Int) {
  • // function body goes here, and can use localParameterName
  • // to refer to the argument value for that parameter
  • }

NOTE

If you provide an external parameter name for a parameter, that external name must always be used when calling the function.

  • funcjoin(s1: String, s2: String, joiner: String) -> String {
  • returns1 + joiner + s2
  • }

 

  • join(“hello”, “world”, “, “)
  • // returns “hello, world”

 

  • funcjoin(strings1: String, toStrings2: String, withJoinerjoiner: String)
  • -> String {
  • returns1 + joiner + s2
  • }

 

  • join(string: “hello”, toString: “world”, withJoiner: “, “)
  • // returns “hello, world”

 

Shorthand External Parameter Names

  • funccontainsCharacter(#string: String, #characterToFind: Character) -> Bool {
  • forcharacterinstring {
  • ifcharacter == characterToFind {
  • returntrue
  • }
  • }
  • returnfalse
  • }

 

  • letcontainsAVee = containsCharacter(string: “aardvark”, characterToFind: “v”)
  • // containsAVee equals true, because “aardvark” contains a “v”
  • funcjoin(strings1: String, toStrings2: String,
  • withJoinerjoiner: String = ” “) -> String {
  • returns1 + joiner + s2
  • }

Default Parameter Values

 

  • join(string: “hello”, toString: “world”, withJoiner: “-“)
  • // returns “hello-world”

However, if no value of joiner is provided when the function is called, the default value of a single space (” “) is used instead:

  • join(string: “hello”, toString: “world”)
  • // returns “hello world”
  • funcjoin(s1: String, s2: String, joiner: String = ” “) -> String {
  • returns1 + joiner + s2
  • }

External Names for Parameters with Default Values

 

  • join(“hello”, “world”, joiner: “-“)
  • // returns “hello-world”
  • funcarithmeticMean(numbers: Double…) -> Double {
  • vartotal: Double = 0
  • fornumberinnumbers {
  • total += number
  • }
  • returntotal / Double(numbers.count)
  • }
  • arithmeticMean(1, 2, 3, 4, 5)
  • // returns 3.0, which is the arithmetic mean of these five numbers
  • arithmeticMean(3, 8, 19)
  • // returns 10.0, which is the arithmetic mean of these three numbers

Variadic Parameters

Constant and Variable Parameters

Function parameters are constants by default. Trying to change the value of a function parameter from within the body of that function results in a compile-time error. This means that you can’t change the value of a parameter by mistake.

However, sometimes it is useful for a function to have a variable copy of a parameter’s value to work with. You can avoid defining a new variable yourself within the function by specifying one or more parameters asvariable parameters instead. Variable parameters are available as variables rather than as constants, and give a new modifiable copy of the parameter’s value for your function to work with.

Define variable parameters by prefixing the parameter name with the keyword var:

  • funcalignRight(varstring: String, count: Int, pad: Character) -> String {
  • letamountToPad = count – countElements(string)
  • ifamountToPad < 1 {
  • returnstring
  • }
  • for_in1…amountToPad {
  • string = pad + string
  • }
  • returnstring
  • }
  • letoriginalString = “hello”
  • letpaddedString = alignRight(originalString, 10, “-“)
  • // paddedString is equal to “—–hello”
  • // originalString is still equal to “hello”
  • funcswapTwoInts(inouta: Int, inoutb: Int) {
  • lettemporaryA = a
  • a = b
  • b = temporaryA
  • }

In-Out Parameters

 

  • varsomeInt = 3
  • varanotherInt = 107
  • swapTwoInts(&someInt, &anotherInt)
  • println(“someInt is now \(someInt), and anotherInt is now \(anotherInt)”)
  • // prints “someInt is now 107, and anotherInt is now 3″

 

Function Types

  • funcaddTwoInts(a: Int, b: Int) -> Int {
  • returna + b
  • }
  • funcmultiplyTwoInts(a: Int, b: Int) -> Int {
  • returna * b
  • }

This example defines two simple mathematical functions called addTwoInts and multiplyTwoInts. These functions each take two Int values, and return an Int value, which is the result of performing an appropriate mathematical operation.

The type of both of these functions is (Int, Int) -> Int. This can be read as:

“A function type that has two parameters, both of type Int, and that returns a value of type Int.”

Here’s another example, for a function with no parameters or return value:

  • funcprintHelloWorld() {
  • println(“hello, world”)
  • }

The type of this function is () -> (), or “a function that has no parameters, and returns Void.” Functions that don’t specify a return value always return Void, which is equivalent to an empty tuple in Swift, shown as().

Using Function Types

  • varmathFunction: (Int, Int) -> Int = addTwoInts
  • println(“Result: \(mathFunction(2, 3))”)
  • // prints “Result: 5″

 

  • mathFunction = multiplyTwoInts
  • println(“Result: \(mathFunction(2, 3))”)
  • // prints “Result: 6″

 

  • letanotherMathFunction = addTwoInts
  • // anotherMathFunction is inferred to be of type (Int, Int) -> Int
  • funcprintMathResult(mathFunction: (Int, Int) -> Int, a: Int, b: Int) {
  • println(“Result: \(mathFunction(a, b))”)
  • }
  • printMathResult(addTwoInts, 3, 5)
  • // prints “Result: 8″

Function Types as Parameter Types

Function Types as Return Types

 

  • funcstepForward(input: Int) -> Int {
  • returninput + 1
  • }
  • funcstepBackward(input: Int) -> Int {
  • returninput – 1
  • }

 

  • funcchooseStepFunction(backwards: Bool) -> (Int) -> Int {
  • returnbackwards ? stepBackward : stepForward
  • }

 

  • varcurrentValue = 3
  • letmoveNearerToZero = chooseStepFunction(currentValue > 0)
  • // moveNearerToZero now refers to the stepBackward() function

 

  • println(“Counting to zero:”)
  • // Counting to zero:
  • whilecurrentValue != 0 {
  • println(“\(currentValue)… “)
  • currentValue = moveNearerToZero(currentValue)
  • }
  • println(“zero!”)
  • // 3…
  • // 2…
  • // 1…
  • // zero!

Nested Functions

 

  • funcchooseStepFunction(backwards: Bool) -> (Int) -> Int {
  • funcstepForward(input: Int) -> Int { returninput + 1 }
  • funcstepBackward(input: Int) -> Int { returninput – 1 }
  • returnbackwards ? stepBackward : stepForward
  • }
  • varcurrentValue = -4
  • letmoveNearerToZero = chooseStepFunction(currentValue > 0)
  • // moveNearerToZero now refers to the nested stepForward() function
  • whilecurrentValue != 0 {
  • println(“\(currentValue)… “)
  • currentValue = moveNearerToZero(currentValue)
  • }
  • println(“zero!”)
  • // -4…
  • // -3…
  • // -2…
  • // -1…
  • // zero!

 

Closures

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.

Closures can capture and store references to any constants and variables from the context in which they are defined. This is known as closing over those constants and variables, hence the name “closures”. Swift handles all of the memory management of capturing for you.

 

Global and nested functions, as introduced in functions are actually special cases of closures. Closures take one of three forms:

  • Global functions are closures that have a name and do not capture any values.
  • Nested functions are closures that have a name and can capture values from their enclosing function.
  • Closure expressions are unnamed closures written in a lightweight syntax that can capture values from their surrounding context.

Swift’s closure expressions have a clean, clear style, with optimizations that encourage brief, clutter-free syntax in common scenarios. These optimizations include:

  • Inferring parameter and return value types from context
  • Implicit returns from single-expression closures
  • Shorthand argument names
  • Trailing closure syntax
  • letnames = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

Closure Expressions

The Sorted Function

The sorted function takes two arguments:

  • An array of values of a known type.
  • A closure that takes two arguments of the same type as the array’s contents, and returns aBool value to say whether the first value should appear before or after the second value once the values are sorted. The sorting closure needs to return true if the first value should appear before the second value, and false
  • funcbackwards(s1: String, s2: String) -> Bool {
  • returns1 > s2
  • }
  • varreversed = sorted(names, backwards)
  • // reversed is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

Closure Expression Syntax

Closure expression syntax has the following general form:

·         { (parameters) -> return type in·             statements·         }

The example below shows a closure expression version of the backwards function from earlier:

  • reversed = sorted(names, { (s1: String, s2: String) -> Boolin
  • returns1 > s2
  • })

Because the body of the closure is so short, it can even be written on a single line:

  • reversed = sorted(names, { (s1: String, s2: String) -> Boolinreturns1 > s2 } )
  • reversed = sorted(names, { s1, s2inreturns1 > s2 } )

Inferring Type From Context

Implicit Returns from Single-Expression Closures

Single-expression closures can implicitly return the result of their single expression by omitting the returnkeyword from their declaration, as in this version of the previous example:

  • reversed = sorted(names, { s1, s2ins1 > s2 } )

Shorthand Argument Names

The in keyword can also be omitted, because the closure expression is made up entirely of its body:

  • reversed = sorted(names, { $0 > $1 } )

Operator Functions

There’s actually an even shorter way to write the closure expression above. Swift’s String type defines its string-specific implementation of the greater-than operator (>) as a function that has two parameters of typeString, and returns a value of type Bool. This exactly matches the function type needed for the sortedfunction’s second parameter. Therefore, you can simply pass in the greater-than operator, and Swift will infer that you want to use its string-specific implementation:

  • reversed = sorted(names, >)
  • funcsomeFunctionThatTakesAClosure(closure: () -> ()) {
  • // function body goes here
  • }
  • // here’s how you call this function without using a trailing closure:
  • someFunctionThatTakesAClosure({
  • // closure’s body goes here
  • })
  • // here’s how you call this function with a trailing closure instead:
  • someFunctionThatTakesAClosure() {
  • // trailing closure’s body goes here
  • }

Trailing Closures

 

  • letdigitNames = [
  • 0: "Zero", 1: "One", 2: "Two", 3: "Three", 4: "Four",
  • 5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
  • ]
  • letnumbers = [16, 58, 510]
  • letstrings = numbers.map {
  • (var number) -> String in
  • varoutput = “”
  • whilenumber > 0 {
  • output = digitNames[number % 10]! + output
  • number /= 10
  • }
  • returnoutput
  • }
  • // strings is inferred to be of type [String]
  • // its value is ["OneSix", "FiveEight", "FiveOneZero"]

Capturing Values

A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.

The simplest form of a closure in Swift is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.

  • funcmakeIncrementor(forIncrementamount: Int) -> () -> Int {
  • varrunningTotal = 0
  • funcincrementor() -> Int {
  • runningTotal += amount
  • returnrunningTotal
  • }
  • returnincrementor
  • }

Closures Are Reference Types

In the example above, incrementBySeven and incrementByTen are constants, but the closures these constants refer to are still able to increment the runningTotal variables that they have captured. This is because functions and closures are reference types.

Whenever you assign a function or a closure to a constant or a variable, you are actually setting that constant or variable to be a reference to the function or closure.

 

Enumerations

Enumeration Syntax

  • enumSomeEnumeration {
  • // enumeration definition goes here
  • }

Here’s an example for the four main points of a compass:

  • enumCompassPoint {
  • caseNorth
  • caseSouth
  • caseEast
  • caseWest
  • }

The values defined in an enumeration (such as North, South, East, and West) are the member values (ormembers) of that enumeration. The case keyword indicates that a new line of member values is about to be defined.

  • enumPlanet {
  • caseMercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  • }
  • vardirectionToHead = CompassPoint.West

Once directionToHead is declared as a CompassPoint, you can set it to a different CompassPoint value using a shorter dot syntax:

  • directionToHead = .East

Matching Enumeration Values with a Switch Statement

You can match individual enumeration values with a switch statement:

  • directionToHead = .South
  • switchdirectionToHead {
  • case .North:
  • println(“Lots of planets have a north”)
  • case .South:
  • println(“Watch out for penguins”)
  • case .East:
  • println(“Where the sun rises”)
  • case .West:
  • println(“Where the skies are blue”)
  • }
  • // prints “Watch out for penguins”

When it is not appropriate to provide a case for every enumeration member, you can provide a default case to cover any members that are not addressed explicitly:

  • letsomePlanet = Planet.Earth
  • switchsomePlanet {
  • case .Earth:
  • println(“Mostly harmless”)
  • default:
  • println(“Not a safe place for humans”)
  • }
  • // prints “Mostly harmless”
  • enumBarcode {
  • caseUPCA(Int, Int, Int, Int)
  • caseQRCode(String)
  • }

Associated Values

New barcodes can then be created using either type:

  • varproductBarcode = Barcode.UPCA(8, 85909, 51226, 3)

The same product can be assigned a different type of barcode:

  • productBarcode = .QRCode(“ABCDEFGHIJKLMNOP”)

 

You extract each associated value as a constant (with the let prefix) or a variable (with the var prefix) for use within the switch case’s body:

  • switchproductBarcode {
  • case .UPCA(letnumberSystem, letmanufacturer, letproduct, letcheck):
  • println(“UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).”)
  • case .QRCode(letproductCode):
  • println(“QR code: \(productCode).”)
  • }
  • // prints “QR code: ABCDEFGHIJKLMNOP.”

If all of the associated values for a enumeration member are extracted as constants, or if all are extracted as variables, you can place a single var or let annotation before the member name, for brevity:

  • switchproductBarcode {
  • caselet .UPCA(numberSystem, manufacturer, product, check):
  • println(“UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).”)
  • caselet .QRCode(productCode):
  • println(“QR code: \(productCode).”)
  • }
  • // prints “QR code: ABCDEFGHIJKLMNOP.”

Raw Values

The barcode example in Associated Values shows how members of an enumeration can declare that they store associated values of different types. As an alternative to associated values, enumeration members can come prepopulated with default values (called raw values), which are all of the same type.

  • enumASCIIControlCharacter: Character {
  • caseTab = “\t”
  • caseLineFeed = “\n”
  • caseCarriageReturn = “\r”
  • }

 

  • enumPlanet: Int {
  • caseMercury = 1, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune
  • }

Access the raw value of an enumeration member with its toRaw method:

  • letearthsOrder = Planet.Earth.toRaw()
  • // earthsOrder is 3

Use an enumeration’s fromRaw method to try to find an enumeration member with a particular raw value. This example identifies Uranus from its raw value of 7:

  • letpossiblePlanet = Planet.fromRaw(7)
  • // possiblePlanet is of type Planet? and equals Planet.Uranus

 

If you try to find a Planet with a position of 9, the optional Planet value returned by fromRaw will be nil:

  • letpositionToFind = 9
  • ifletsomePlanet = Planet.fromRaw(positionToFind) {
  • switchsomePlanet {
  • case .Earth:
  • println(“Mostly harmless”)
  • default:
  • println(“Not a safe place for humans”)
  • }
  • } else {
  • println(“There isn’t a planet at position \(positionToFind)”)
  • }
  • // prints “There isn’t a planet at position 9″

 

Classes and Structures

Comparing Classes and Structures

Classes and structures 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 do not:

  • 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.
  • classSomeClass {
  • // class definition goes here
  • }
  • structSomeStructure {
  • // structure definition goes here
  • }

Definition Syntax

Here’s an example of a structure definition and a class definition:

  • structResolution {
  • varwidth = 0
  • varheight = 0
  • }
  • classVideoMode {
  • varresolution = Resolution()
  • varinterlaced = false
  • varframeRate = 0
  • varname: String?
  • }

 

Class and Structure Instances

The syntax for creating instances is very similar for both structures and classes:

  • letsomeResolution = Resolution()
  • letsomeVideoMode = VideoMode()
  • println(“The width of someResolution is \(someResolution.width)”)
  • // prints “The width of someResolution is 0″

 

Accessing Properties

 

  • println(“The width of someVideoMode is \(someVideoMode.resolution.width)”)
  • // prints “The width of someVideoMode is 0″

 

You can also use dot syntax to assign a new value to a variable property:

  • someVideoMode.resolution.width = 1280
  • println(“The width of someVideoMode is now \(someVideoMode.resolution.width)”)
  • // prints “The width of someVideoMode is now 1280″

 

Memberwise Initializers for Structure Types

Initial values for the properties of the new instance can be passed to the memberwise initializer by name:

  • letvga = Resolution(width: 640, height: 480)

Unlike structures, class instances do not receive a default memberwise initializer.

Structures and Enumerations Are Value Types

value type is a type whose value is copied when it is assigned to a variable or constant, or when it is passed to a function.

 

All structures and enumerations are value types in Swift. This means that any structure and enumeration instances you create—and any value types they have as properties—are always copied when they are passed around in your code.

  • lethd = Resolution(width: 1920, height: 1080)
  • varcinema = hd
  • cinema.width = 2048
  • println(“cinema is now \(cinema.width) pixels wide”)
  • // prints “cinema is now 2048 pixels wide”
  • println(“hd is still \(hd.width) pixels wide”)
  • // prints “hd is still 1920 pixels wide”

 

  • enumCompassPoint {
  • caseNorth, South, East, West
  • }
  • varcurrentDirection = CompassPoint.West
  • letrememberedDirection = currentDirection
  • currentDirection = .East
  • ifrememberedDirection == .West {
  • println(“The remembered direction is still .West”)
  • }
  • // prints “The remembered direction is still .West”

Classes Are Reference Types

Unlike value 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.

 

Here’s an example, using the VideoMode class defined above:

  • lettenEighty = VideoMode()
  • tenEighty.resolution = hd
  • tenEighty.interlaced = true
  • tenEighty.name = “1080i”
  • tenEighty.frameRate = 0

 

  • letalsoTenEighty = tenEighty
  • alsoTenEighty.frameRate = 0

 

  • println(“The frameRate property of tenEighty is now \(tenEighty.frameRate)”)
  • // prints “The frameRate property of tenEighty is now 30.0″

 

Identity Operators

Because classes are reference types, it is possible for multiple constants and variables to refer to the same single instance of a class behind the scenes. (The same is not true for structures and enumerations, because they are always copied when they are assigned to a constant or variable, or passed to a function.)

It can sometimes be useful to find out if two constants or variables refer to exactly the same instance of a class. To enable this, Swift provides two identity operators:

  • Identical to (===)
  • Not identical to (!==)

 

Use these operators to check whether two constants or variables refer to the same single instance:

  • iftenEighty === alsoTenEighty {
  • println(“tenEighty and alsoTenEighty refer to the same VideoMode instance.”)
  • }
  • // prints “tenEighty and alsoTenEighty refer to the same VideoMode instance.”

 

Pointers

If you have experience with C, C++, or Objective-C, you may know that these languages use pointers to refer to addresses in memory. 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, and does not require you to write an asterisk (*) to indicate that you are creating a reference. Instead, these references are defined like any other constant or variable in Swift.

Choosing Between Classes and Structures

As a general guideline, consider creating a structure when one or more of these conditions apply:

  • The structure’s primary purpose is to encapsulate a few relatively simple data values.
  • It is reasonable to expect that the encapsulated values will be copied rather than referenced when you assign or pass around an instance of that structure.
  • Any properties stored by the structure are themselves value types, which would also be expected to be copied rather than referenced.
  • The structure does not need to inherit properties or behavior from another existing type.

Examples of good candidates for structures include:

  • The size of a geometric shape, perhaps encapsulating awidth property and a height property, both of type Double.
  • A way to refer to ranges within a series, perhaps encapsulating astart property and a lengthproperty, both of type Int.
  • A point in a 3D coordinate system, perhaps encapsulatingx, y and z properties, each of type Double.

 

In all other cases, define a class, and create instances of that class to be managed and passed by reference. In practice, this means that most custom data constructs should be classes, not structures.

Assignment and Copy Behavior for Strings, Arrays, and Dictionaries

Swift’s String, Array, and Dictionary types are implemented as structures. This means that strings, arrays, and dictionaries are copied when they are assigned to a new constant or variable, or when they are passed to a function or method.

 

This behavior is different from NSString, NSArray, and NSDictionary in Foundation, which are implemented as classes, not structures. NSString, NSArray, and NSDictionary instances are always assigned and passed around as a reference to an existing instance, rather than as a copy.

 

The description above refers to the “copying” of strings, arrays, and dictionaries. The behavior you see in your code will always be as if a copy took place. However, Swift only performs an actual copy behind the scenes when it is absolutely necessary to do so. Swift manages all value copying to ensure optimal performance, and you should not avoid assignment to try to preempt this optimization.

 

Properties

 

Properties associate values with a particular class, structure, or enumeration. Stored properties store constant and variable values as part of an instance, whereas computed properties calculate (rather than store) a value. Computed properties are provided by classes, structures, and enumerations. Stored properties are provided only by classes and structures.

 

Stored and computed properties are usually associated with instances of a particular type. However, properties can also be associated with the type itself. Such properties are known as type properties.

In addition, you can define property observers to monitor changes in a property’s value, which you can respond to with custom actions. Property observers can be added to stored properties you define yourself, and also to properties that a subclass inherits from its superclass.

Stored Properties

In its simplest form, a stored property is a constant or variable that is stored as part of an instance of a particular class or structure. Stored properties can be either variable stored properties (introduced by thevar keyword) or constant stored properties (introduced by the let keyword).

  • structFixedLengthRange {
  • varfirstValue: Int
  • letlength: Int
  • }
  • varrangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
  • // the range represents integer values 0, 1, and 2
  • rangeOfThreeItems.firstValue = 6
  • // the range now represents integer values 6, 7, and 8

Instances of FixedLengthRange have a variable stored property called firstValue and a constant stored property called length. In the example above, length is initialized when the new range is created and cannot be changed thereafter, because it is a constant property.

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:

  • letrangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
  • // this range represents integer values 0, 1, 2, and 3
  • rangeOfFourItems.firstValue = 6
  • // this will report an error, even though firstValue is a variable property

Because rangeOfFourItems is declared as a constant (with the let keyword), it is not possible to change itsfirstValue property, even though firstValue is a variable property.

 

This behavior is due to structures being value types. When an instance of a value type is marked as a constant, so are all of its properties.

The same is not true for classes, which are reference types. If you assign an instance of a reference type to a constant, you can still change that instance’s variable properties.

Lazy Stored Properties

lazy stored property is a property whose initial value is not calculated until the first time it is used. You indicate a lazy stored property by writing the lazy modifier before its declaration.

  • classDataImporter {
  • /*
  • 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.
  • */
  • varfileName = “data.txt”
  • // the DataImporter class would provide data importing functionality here
  • }
  • classDataManager {
  • lazyvarimporter = DataImporter()
  • vardata = [String]()
  • // the DataManager class would provide data management functionality here
  • }
  • letmanager = DataManager()
  • manager.data.append(“Some data”)
  • manager.data.append(“Some more data”)
  • // the DataImporter instance for the importer property has not yet been created

 

  • println(manager.importer.fileName)
  • // the DataImporter instance for the importer property has now been created
  • // prints “data.txt”
  • structPoint {
  • varx = 0, y = 0.0
  • }
  • structSize {
  • varwidth = 0, height = 0.0
  • }
  • structRect {
  • varorigin = Point()
  • varsize = Size()
  • varcenter: Point {
  • get {
  • letcenterX = origin.x + (size.width / 2)
  • letcenterY = origin.y + (size.height / 2)
  • returnPoint(x: centerX, y: centerY)
  • }
  • set(newCenter) {
  • origin.x = newCenter.x – (size.width / 2)
  • origin.y = newCenter.y – (size.height / 2)
  • }
  • }
  • }
  • varsquare = Rect(origin: Point(x: 0, y: 0.0),
  • size: Size(width: 0, height: 10.0))
  • letinitialSquareCenter = square.center
  • square.center = Point(x: 0, y: 15.0)
  • println(“square.origin is now at (\(square.origin.x), \(square.origin.y))”)
  • // prints “square.origin is now at (10.0, 10.0)”

Stored Properties and Instance Variables

Computed Properties

This example defines three structures for working with geometric shapes:

  • Pointencapsulates an (x, y)
  • Sizeencapsulates a width and a height.
  • Rectdefines a rectangle by an origin point and a size.

 

Shorthand Setter Declaration

  • structAlternativeRect {
  • varorigin = Point()
  • varsize = Size()
  • varcenter: Point {
  • get {
  • letcenterX = origin.x + (size.width / 2)
  • letcenterY = origin.y + (size.height / 2)
  • returnPoint(x: centerX, y: centerY)
  • }
  • set {
  • origin.x = newValue.x – (size.width / 2)
  • origin.y = newValue.y – (size.height / 2)
  • }
  • }
  • }

Read-Only Computed Properties

You can simplify the declaration of a read-only computed property by removing the get keyword and its braces:

  • structCuboid {
  • varwidth = 0, height = 0.0, depth = 0.0
  • varvolume: Double {
  • returnwidth * height * depth
  • }
  • }
  • letfourByFiveByTwo = Cuboid(width: 0, height: 5.0, depth: 2.0)
  • println(“the volume of fourByFiveByTwo is \(fourByFiveByTwo.volume)”)
  • // prints “the volume of fourByFiveByTwo is 40.0″

Property Observers

Property observers observe and respond to changes in a property’s value. Property observers are called every time a property’s value is set, even if the new value is the same as the property’s current value.

You can add property observers to any stored properties you define, apart from lazy stored properties. You can also add property observers to any inherited property (whether stored or computed) by overriding the property within a subclass.

You have the option to define either or both of these observers on a property:

  • willSetis called just before the value is stored.
  • didSetis called immediately after the new value is stored.

 

  • classStepCounter {
  • vartotalSteps: Int = 0 {
  • willSet(newTotalSteps) {
  • println(“About to set totalSteps to \(newTotalSteps)”)
  • }
  • didSet {
  • iftotalSteps > oldValue {
  • println(“Added \(totalSteps – oldValue) steps”)
  • }
  • }
  • }
  • }
  • letstepCounter = StepCounter()
  • stepCounter.totalSteps = 200
  • // About to set totalSteps to 200
  • // Added 200 steps
  • stepCounter.totalSteps = 360
  • // About to set totalSteps to 360
  • // Added 160 steps
  • stepCounter.totalSteps = 896
  • // About to set totalSteps to 896
  • // Added 536 steps

Global and Local Variables

The capabilities described above for computing and observing properties are also available to global variables and local variables. Global variables are variables that are defined outside of any function, method, closure, or type context. Local variables are variables that are defined within a function, method, or closure context.

The global and local variables you have encountered in previous chapters have all been stored variables. Stored variables, like stored properties, provide storage for a value of a certain type and allow that value to be set and retrieved.

However, you can also define computed variables and define observers for stored variables, in either a global or local scope.

Type Properties

Instance properties are properties that belong to an instance of a particular type. Every time you create a new instance of that type, it has its own set of property values, separate from any other instance.

You can also define properties that belong to the type itself, not to any one instance of that type. There will only ever be one copy of these properties, no matter how many instances of that type you create. These kinds of properties are called 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).

For value types (that is, structures and enumerations), you can define stored and computed type properties. For classes, you can define computed type properties only.

Stored type properties for value types can be variables or constants. Computed type properties are always declared as variable properties, in the same way as computed instance properties.

Type Property Syntax

You define type properties for value types with the static keyword, and type properties for class types with the class keyword. The example below shows the syntax for stored and computed type properties:

  • structSomeStructure {
  • staticvarstoredTypeProperty = “Some value.”
  • staticvarcomputedTypeProperty: Int {
  • // return an Int value here
  • }
  • }
  • enumSomeEnumeration {
  • staticvarstoredTypeProperty = “Some value.”
  • staticvarcomputedTypeProperty: Int {
  • // return an Int value here
  • }
  • }
  • classSomeClass {
  • classvarcomputedTypeProperty: Int {
  • // return an Int value here
  • }
  • }

Querying and Setting Type Properties

Type properties are queried and set with dot syntax, just like instance properties. However, type properties are queried and set on the type, not on an instance of that type. For example:

  • println(SomeClass.computedTypeProperty)
  • // prints “42”
  • println(SomeStructure.storedTypeProperty)
  • // prints “Some value.”
  • SomeStructure.storedTypeProperty = “Another value.”
  • println(SomeStructure.storedTypeProperty)
  • // prints “Another value.”

The audio channels described above are represented by instances of the AudioChannel structure:

  • structAudioChannel {
  • staticletthresholdLevel = 10
  • staticvarmaxInputLevelForAllChannels = 0
  • varcurrentLevel: Int = 0 {
  • didSet {
  • ifcurrentLevel > AudioChannel.thresholdLevel {
  • // cap the new audio level to the threshold level
  • currentLevel = AudioChannel.thresholdLevel
  • }
  • ifcurrentLevel > AudioChannel.maxInputLevelForAllChannels {
  • // store this as the new overall maximum input level
  • AudioChannel.maxInputLevelForAllChannels = currentLevel
  • }
  • }
  • }
  • }
  • varleftChannel = AudioChannel()
  • varrightChannel = AudioChannel()

 

  • leftChannel.currentLevel = 7
  • println(leftChannel.currentLevel)
  • // prints “7”
  • println(AudioChannel.maxInputLevelForAllChannels)
  • // prints “7”

 

  • rightChannel.currentLevel = 11
  • println(rightChannel.currentLevel)
  • // prints “10”
  • println(AudioChannel.maxInputLevelForAllChannels)
  • // prints “10”

 

 

Methods

 

Methods are functions that are associated with a particular type. Classes, structures, and enumerations can all define instance methods, which encapsulate specific tasks and functionality for working with an instance of a given type. Classes, structures, and enumerations can also define type methods, which are associated with the type itself. Type methods are similar to class methods in Objective-C.

The fact that structures and enumerations can define methods in Swift is a major difference from C and Objective-C. In Objective-C, classes are the only types that can define methods. In Swift, you can choose whether to define a class, structure, or enumeration, and still have the flexibility to define methods on the type you create.

Instance Methods

  • classCounter {
  • varcount = 0
  • funcincrement() {
  • count++
  • }
  • funcincrementBy(amount: Int) {
  • count += amount
  • }
  • funcreset() {
  • count = 0
  • }
  • }

 

  • letcounter = Counter()
  • // the initial counter value is 0
  • counter.increment()
  • // the counter’s value is now 1
  • counter.incrementBy(5)
  • // the counter’s value is now 6
  • counter.reset()
  • // the counter’s value is now 0

Local and External Parameter Names for Methods

Consider this alternative version of the Counter class, which defines a more complex form of the incrementBymethod:

  • classCounter {
  • varcount: Int = 0
  • funcincrementBy(amount: Int, numberOfTimes: Int) {
  • count += amount * numberOfTimes
  • }
  • }

 

  • letcounter = Counter()
  • counter.incrementBy(5, numberOfTimes: 3)
  • // counter value is now 15

 

  • funcincrementBy(amount: Int, #numberOfTimes: Int) {
  • count += amount * numberOfTimes
  • }

 

Modifying External Parameter Name Behavior for Methods

Sometimes it’s useful to provide an external parameter name for a method’s first parameter, even though this is not the default behavior. You can either add an explicit external name yourself, or you can prefix the first parameter’s name with a hash symbol to use the local name as an external name too.

Conversely, if you do not want to provide an external name for the second or subsequent parameter of a method, override the default behavior by using an underscore character (_) as an explicit external parameter name for that parameter.

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.

  • funcincrement() {
  • self.count++
  • }

Here, self disambiguates between a method parameter called x and an instance property that is also calledx:

  • structPoint {
  • varx = 0, y = 0.0
  • funcisToTheRightOfX(x: Double) -> Bool {
  • returnself.x > x
  • }
  • }
  • letsomePoint = Point(x: 0, y: 5.0)
  • ifsomePoint.isToTheRightOfX(0) {
  • println(“This point is to the right of the line where x == 1.0″)
  • }
  • // prints “This point is to the right of the line where x == 1.0″

Without the self prefix, Swift would assume that both uses of x referred to the method parameter called x.

Modifying Value Types from Within Instance Methods

Structures and enumerations are value types. By default, the properties of a value type cannot be modified from within its instance methods.

However, 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. You can opt in to this behavior by placing the mutating keyword before the func keyword for that method:

  • structPoint {
  • varx = 0, y = 0.0
  • mutatingfuncmoveByX(deltaX: Double, ydeltaY: Double) {
  • x += deltaX
  • y += deltaY
  • }
  • }
  • varsomePoint = Point(x: 0, y: 1.0)
  • somePoint.moveByX(0, y: 3.0)
  • println(“The point is now at (\(somePoint.x), \(somePoint.y))”)
  • // prints “The point is now at (3.0, 4.0)”

 

  • letfixedPoint = Point(x: 0, y: 3.0)
  • fixedPoint.moveByX(0, y: 3.0)
  • // this will report an error

Assigning to self Within a Mutating Method

Mutating methods can assign an entirely new instance to the implicit self property. The Point example shown above could have been written in the following way instead:

  • structPoint {
  • varx = 0, y = 0.0
  • mutatingfuncmoveByX(deltaX: Double, ydeltaY: Double) {
  • self = Point(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:

  • enumTriStateSwitch {
  • caseOff, Low, High
  • mutatingfuncnext() {
  • switchself {
  • caseOff:
  • self = Low
  • caseLow:
  • self = High
  • caseHigh:
  • self = Off
  • }
  • }
  • }
  • varovenLight = TriStateSwitch.Low
  • ovenLight.next()
  • // ovenLight is now equal to .High
  • ovenLight.next()
  • // ovenLight is now equal to .Off
  • classSomeClass {
  • classfuncsomeTypeMethod() {
  • // type method implementation goes here
  • }
  • }
  • SomeClass.someTypeMethod()

Type Methods

 

  • structLevelTracker {
  • staticvarhighestUnlockedLevel = 1
  • staticfuncunlockLevel(level: Int) {
  • iflevel > highestUnlockedLevel { highestUnlockedLevel = level }
  • }
  • staticfunclevelIsUnlocked(level: Int) -> Bool {
  • returnlevel <= highestUnlockedLevel
  • }
  • varcurrentLevel = 1
  • mutatingfuncadvanceToLevel(level: Int) -> Bool {
  • ifLevelTracker.levelIsUnlocked(level) {
  • currentLevel = level
  • returntrue
  • } else {
  • returnfalse
  • }
  • }
  • }

 

  • classPlayer {
  • vartracker = LevelTracker()
  • letplayerName: String
  • funccompletedLevel(level: Int) {
  • LevelTracker.unlockLevel(level + 1)
  • tracker.advanceToLevel(level + 1)
  • }
  • init(name: String) {
  • playerName = name
  • }
  • }

 

  • varplayer = Player(name: “Argyrios”)
  • player.completedLevel(1)
  • println(“highest unlocked level is now \(LevelTracker.highestUnlockedLevel)”)
  • // prints “highest unlocked level is now 2″

 

  • player = Player(name: “Beto”)
  • ifplayer.tracker.advanceToLevel(6) {
  • println(“player is now on level 6″)
  • } else {
  • println(“level 6 has not yet been unlocked”)
  • }
  • // prints “level 6 has not yet been unlocked”

 

Subscripts

Classes, structures, and enumerations can define subscripts, which are shortcuts for accessing the member elements of a collection, list, or sequence. You use subscripts to set and retrieve values by index without needing separate methods for setting and retrieval.

Subscript Syntax

 

  • subscript(index: Int) -> Int {
  • get {
  • // return an appropriate subscript value here
  • }
  • set(newValue) {
  • // perform a suitable setting action here
  • }
  • }

 

  • subscript(index: Int) -> Int {
  • // return an appropriate subscript value here
  • }

 

  • structTimesTable {
  • letmultiplier: Int
  • subscript(index: Int) -> Int {
  • returnmultiplier * index
  • }
  • }
  • letthreeTimesTable = TimesTable(multiplier: 3)
  • println(“six times three is \(threeTimesTable[6])”)
  • // prints “six times three is 18″

 

Subscript Options

Subscripts can take any number of input parameters, and these input parameters can be of any type. Subscripts can also return any type. Subscripts can use variable parameters and variadic parameters, but cannot use in-out parameters or provide default parameter values.

  • structMatrix {
  • letrows: Int, columns: Int
  • vargrid: [Double]
  • init(rows: Int, columns: Int) {
  • self.rows = rows
  • self.columns = columns
  • grid = Array(count: rows * columns, repeatedValue: 0)
  • }
  • funcindexIsValidForRow(row: Int, column: Int) -> Bool {
  • returnrow >= 0 && row < rows && column >= 0 && column < columns
  • }
  • subscript(row: Int, column: Int) -> Double {
  • get {
  • assert(indexIsValidForRow(row, column: column), “Index out of range”)
  • returngrid[(row * columns) + column]
  • }
  • set {
  • assert(indexIsValidForRow(row, column: column), “Index out of range”)
  • grid[(row * columns) + column] = newValue
  • }
  • }
  • }
  • varmatrix = Matrix(rows: 2, columns: 2)

 

  • matrix[0, 1] = 5
  • matrix[1, 0] = 2

 

  • funcindexIsValidForRow(row: Int, column: Int) -> Bool {
  • returnrow >= 0 && row < rows && column >= 0 && column < columns
  • }
  • // this triggers an assert, because [2, 2] is outside of the matrix bounds

letsomeValue =matrix[2,2]

 

Inheritance

On This Page

A class can inherit methods, properties, and other characteristics from another class. When one class inherits from another, the inheriting class is known as a subclass, and the class it inherits from is known as its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.

Classes in Swift can call and access methods, properties, and subscripts belonging to their superclass and can provide their own overriding versions of those methods, properties, and subscripts to refine or modify their behavior. Swift helps to ensure your overrides are correct by checking that the override definition has a matching superclass definition.

Classes can also add property observers to inherited properties in order to be notified when the value of a property changes. Property observers can be added to any property, regardless of whether it was originally defined as a stored or computed property.

Defining a Base Class

  • classVehicle {
  • varcurrentSpeed = 0
  • vardescription: String {
  • return”traveling at \(currentSpeed) miles per hour”
  • }
  • funcmakeNoise() {
  • // do nothing – an arbitrary vehicle doesn’t necessarily make a noise
  • }
  • }
  • letsomeVehicle = Vehicle()

 

  • println(“Vehicle: \(someVehicle.description)”)
  • // Vehicle: traveling at 0.0 miles per hour

Subclassing

 

  • classSomeSubclass: SomeSuperclass {
  • // subclass definition goes here
  • }

 

  • classBicycle: Vehicle {
  • varhasBasket = false
  • }

 

  • letbicycle = Bicycle()
  • bicycle.hasBasket = true

 

  • bicycle.currentSpeed = 0
  • println(“Bicycle: \(bicycle.description)”)
  • // Bicycle: traveling at 15.0 miles per hour

 

  • classTandem: Bicycle {
  • varcurrentNumberOfPassengers = 0
  • }

 

  • lettandem = Tandem()
  • tandem.hasBasket = true
  • tandem.currentNumberOfPassengers = 2
  • tandem.currentSpeed = 0
  • println(“Tandem: \(tandem.description)”)
  • // Tandem: traveling at 22.0 miles per hour

Overriding

A subclass can provide its own custom implementation of an instance method, class method, instance property, class property, or subscript that it would otherwise inherit from a superclass. This is known asoverriding.

To override a characteristic that would otherwise be inherited, you prefix your overriding definition with theoverride keyword. Doing so clarifies that you intend to provide an override and have not provided a matching definition by mistake. Overriding by accident can cause unexpected behavior, and any overrides without the override keyword are diagnosed as an error when your code is compiled.

The override keyword also prompts the Swift compiler to check that your overriding class’s superclass (or one of its parents) has a declaration that matches the one you provided for the override. This check ensures that your overriding definition is correct.

Accessing Superclass Methods, Properties, and Subscripts

When you provide a method, property, or subscript override for a subclass, it is sometimes useful to use the existing superclass implementation as part of your override. For example, you can refine the behavior of that existing implementation, or store a modified value in an existing inherited variable.

Where this is appropriate, you access the superclass version of a method, property, or subscript by using the super prefix:

  • An overridden method namedsomeMethod can call the superclass version of someMethod by callingsomeMethod() within the overriding method implementation.
  • An overridden property calledsomeProperty can access the superclass version of someProperty assomeProperty within the overriding getter or setter implementation.
  • An overridden subscript forsomeIndex can access the superclass version of the same subscript assuper[someIndex] from within the overriding subscript implementation.
  • classTrain: Vehicle {
  • overridefuncmakeNoise() {
  • println(“Choo Choo”)
  • }
  • }

Overriding Methods

 

  • lettrain = Train()
  • train.makeNoise()
  • // prints “Choo Choo”

Overriding Properties

You can override an inherited instance or class property to provide your own custom getter and setter for that property, or to add property observers to enable the overriding property to observe when the underlying property value changes.

Overriding Property Getters and Setters

You can provide a custom getter (and setter, if appropriate) to override any inherited property, regardless of whether the inherited property is implemented as a stored or computed property at source. The stored or computed nature of an inherited property is not known by a subclass—it only knows that the inherited property has a certain name and type. You must always state both the name and the type of the property you are overriding, to enable the compiler to check that your override matches a superclass property with the same name and type.

You can present an inherited read-only property as a read-write property by providing both a getter and a setter in your subclass property override. You cannot, however, present an inherited read-write property as a read-only property.

  • classCar: Vehicle {
  • vargear = 1
  • overridevardescription: String {
  • returnsuper.description + ” in gear \(gear)”
  • }
  • }

 

  • letcar = Car()
  • car.currentSpeed = 0
  • car.gear = 3
  • println(“Car: \(car.description)”)
  • // Car: traveling at 25.0 miles per hour in gear 3

Overriding Property Observers

You can use property overriding to add property observers to an inherited property. This enables you to be notified when the value of an inherited property changes, regardless of how that property was originally implemented.:

  • classAutomaticCar: Car {
  • overridevarcurrentSpeed: Double {
  • didSet {
  • gear = Int(currentSpeed / 0) + 1
  • }
  • }
  • }

 

  • letautomatic = AutomaticCar()
  • automatic.currentSpeed = 0
  • println(“AutomaticCar: \(automatic.description)”)
  • // AutomaticCar: traveling at 35.0 miles per hour in gear 4

Preventing Overrides

You can prevent a method, property, or subscript from being overridden by marking it as final. Do this by writing the final modifier before the method, property, or subscript’s introducer keyword (such as final var,final func, final class func, and final subscript).

Any attempts to override a final method, property, or subscript in a subclass are reported as a compile-time error. Methods, properties, or subscripts that you add to a class in an extension can also be marked as final within the extension’s definition.

You can mark an entire class as final by writing the final modifier before the class keyword in its class definition (final class). Any attempts to subclass a final class will be reported as a compile-time error.

 

Initialization

Setting Initial Values for Stored Properties

Classes and structures must set all of their stored properties to an appropriate initial value by the time an instance of that class or structure is created. Stored properties cannot be left in an indeterminate state.

You can set an initial value for a stored property within an initializer, or by assigning a default property value as part of the property’s definition. These actions are described in the following sections.

Initializers

Initializers are called to create a new instance of a particular type. In its simplest form, an initializer is like an instance method with no parameters, written using the init keyword:

  • init() {
  • // perform some initialization here
  • }

 

  • structFahrenheit {
  • vartemperature: Double
  • init() {
  • temperature = 0
  • }
  • }
  • varf = Fahrenheit()
  • println(“The default temperature is \(f.temperature)° Fahrenheit”)
  • // prints “The default temperature is 32.0° Fahrenheit”
  • structFahrenheit {
  • vartemperature = 0
  • }

Default Property Values

Customizing Initialization

You can customize the initialization process with input parameters and optional property types, or by modifying constant properties during initialization, as described in the following sections.

Initialization Parameters

You can provide initialization parameters as part of an initializer’s definition, to define the types and names of values that customize the initialization process.

struct Celsius {

  • vartemperatureInCelsius: Double
  • init(fromFahrenheitfahrenheit: Double) {
  • temperatureInCelsius = (fahrenheit – 0) / 1.8
  • }
  • init(fromKelvinkelvin: Double) {
  • temperatureInCelsius = kelvin – 15
  • }
  • }
  • letboilingPointOfWater = Celsius(fromFahrenheit: 0)
  • // boilingPointOfWater.temperatureInCelsius is 100.0
  • letfreezingPointOfWater = Celsius(fromKelvin: 15)
  • // freezingPointOfWater.temperatureInCelsius is 0.0

Local and External Parameter Names

As with function and method parameters, initialization parameters can have both a local name for use within the initializer’s body and an external name for use when calling the initializer.

 

  • structColor {
  • letred, 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
  • }
  • }

 

  • letmagenta = Color(red: 0, green: 0.0, blue: 1.0)
  • lethalfGray = Color(white: 5)

 

  • letveryGreen = Color(0, 1.0, 0.0)
  • // this reports a compile-time error – external names are required

Initializer Parameters Without External Names

If you do not want to use an external name for an initializer parameter, write an underscore (_) instead of an explicit external name for that parameter to override the default behavior.

  • structCelsius {
  • vartemperatureInCelsius: Double
  • init(fromFahrenheitfahrenheit: Double) {
  • temperatureInCelsius = (fahrenheit – 0) / 1.8
  • }
  • init(fromKelvinkelvin: Double) {
  • temperatureInCelsius = kelvin – 15
  • }
  • init(_celsius: Double) {
  • temperatureInCelsius = celsius
  • }
  • }
  • letbodyTemperature = Celsius(0)
  • // bodyTemperature.temperatureInCelsius is 37.0

Optional Property Types

Properties of optional type are automatically initialized with a value of nil, indicating that the property is deliberately intended to have “no value yet” during initialization.

  • classSurveyQuestion {
  • vartext: String
  • varresponse: String?
  • init(text: String) {
  • self.text = text
  • }
  • funcask() {
  • println(text)
  • }
  • }
  • letcheeseQuestion = SurveyQuestion(text: “Do you like cheese?”)
  • cheeseQuestion.ask()
  • // prints “Do you like cheese?”
  • cheeseQuestion.response = “Yes, I do like cheese.”

 

Modifying Constant Properties During Initialization

 

  • classSurveyQuestion {
  • lettext: String
  • varresponse: String?
  • init(text: String) {
  • self.text = text
  • }
  • funcask() {
  • println(text)
  • }
  • }
  • letbeetsQuestion = SurveyQuestion(text: “How about beets?”)
  • beetsQuestion.ask()
  • // prints “How about beets?”
  • beetsQuestion.response = “I also like beets. (But not with cheese.)”
  • classShoppingListItem {
  • varname: String?
  • varquantity = 1
  • varpurchased = false
  • }
  • varitem = ShoppingListItem()

Default Initializers

 

Memberwise Initializers for Structure Types

  • structSize {
  • varwidth = 0, height = 0.0
  • }
  • lettwoByTwo = Size(width: 0, height: 2.0)
  • structSize {
  • varwidth = 0, height = 0.0
  • }
  • structPoint {
  • varx = 0, y = 0.0
  • }
  • varorigin = Point()
  • varsize = Size()
  • init() {}
  • init(origin: Point, size: Size) {
  • self.origin = origin
  • self.size = size
  • }
  • init(center: Point, size: Size) {
  • letoriginX = center.x – (size.width / 2)
  • letoriginY = center.y – (size.height / 2)
  • self.init(origin: Point(x: originX, y: originY), size: size)
  • }
  • }

Initializer Delegation for Value Types

structRect {

 

  • letbasicRect = Rect()
  • // basicRect’s origin is (0.0, 0.0) and its size is (0.0, 0.0)

 

  • letoriginRect = Rect(origin: Point(x: 0, y: 2.0),
  • size: Size(width: 0, height: 5.0))
  • // originRect’s origin is (2.0, 2.0) and its size is (5.0, 5.0)

 

  • letcenterRect = Rect(center: Point(x: 0, y: 4.0),
  • size: Size(width: 0, height: 3.0))
  • // centerRect’s origin is (2.5, 2.5) and its size is (3.0, 3.0)

Class Inheritance and Initialization

Designated Initializers and Convenience Initializers

 

Syntax for Designated and Convenience Initializers

·         init(parameters) {·             statements·         } ·         convenience init(parameters) {·             statements·         }

Initializer Chaining

To simplify the relationships between designated and convenience initializers, Swift applies the following three rules for delegation calls between initializers:

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.

A simple way to remember this is:

  • Designated initializers must always delegateup.
  • Convenience initializers must always delegateacross.

These rules are illustrated in the figure below:

Two-Phase Initialization

Class initialization in Swift is a two-phase process. In the first phase, each stored property is assigned an initial value by the class that introduced it. Once the initial state for every stored property has been determined, the second phase begins, and each class is given the opportunity to customize its stored properties further before the new instance is considered ready for use.

The use of a two-phase initialization process makes initialization safe, while still giving complete flexibility to each class in a class hierarchy. Two-phase initialization prevents property values from being accessed before they are initialized, and prevents property values from being set to a different value by another initializer unexpectedly.

NOTE

Swift’s two-phase initialization process is similar to initialization in Objective-C. The main difference is that during phase 1, Objective-C assigns zero or null values (such as 0 or nil) to every property. Swift’s initialization flow is more flexible in that it lets you set custom initial values, and can cope with types for which 0 or nil is not a valid default value.

Swift’s compiler performs four helpful safety-checks to make sure that two-phase initialization is completed without error:

Safety check 1

A designated initializer must ensure that all of the properties introduced by its class are initialized before it delegates up to a superclass initializer.

As mentioned above, the memory for an object is only considered fully initialized once the initial state of all of its stored properties is known. In order for this rule to be satisfied, a designated initializer must make sure that all its own properties are initialized before it hands off up the chain.

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 selfas a value until after the first phase of initialization is complete.

The class instance is not fully valid until the first phase ends. Properties can only be accessed, and methods can only be called, once the class instance is known to be valid at the end of the first phase.

Here’s how two-phase initialization plays out, based on the four safety checks above:

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 accessself 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 withself.

Here’s how phase 1 looks for an initialization call for a hypothetical subclass and superclass:

In this example, initialization begins with a call to a convenience initializer on the subclass. This convenience initializer cannot yet modify any properties. It delegates across to a designated initializer from the same class.

The designated initializer makes sure that all of the subclass’s properties have a value, as per safety check 1. It then calls a designated initializer on its superclass to continue the initialization up the chain.

The superclass’s designated initializer makes sure that all of the superclass properties have a value. There are no further superclasses to initialize, and so no further delegation is needed.

As soon as all properties of the superclass have an initial value, its memory is considered fully initialized, and Phase 1 is complete.

Here’s how phase 2 looks for the same initialization call:

The superclass’s designated initializer now has an opportunity to customize the instance further (although it does not have to).

Once the superclass’s designated initializer is finished, the subclass’s designated initializer can perform additional customization (although again, it does not have to).

Finally, once the subclass’s designated initializer is finished, the convenience initializer that was originally called can perform additional customization.

Initializer Inheritance and Overriding

Unlike subclasses in Objective-C, Swift subclasses do not inherit their superclass initializers by default. Swift’s approach prevents a situation in which a simple initializer from a superclass is inherited by a more specialized subclass and is used to create a new instance of the subclass that is not fully or correctly initialized.

 

  • classVehicle {
  • varnumberOfWheels = 0
  • vardescription: String {
  • return”\(numberOfWheels) wheel(s)”
  • }
  • }

 

  • letvehicle = Vehicle()
  • println(“Vehicle: \(vehicle.description)”)
  • // Vehicle: 0 wheel(s)

The next example defines a subclass of Vehicle called Bicycle:

  • classBicycle: Vehicle {
  • overrideinit() {
  • super.init()
  • numberOfWheels = 2
  • }
  • }

 

  • letbicycle = Bicycle()
  • println(“Bicycle: \(bicycle.description)”)
  • // Bicycle: 2 wheel(s)

 

Automatic Initializer Inheritance

As mentioned above, subclasses do not inherit their superclass initializers by default. However, superclass initializers are automatically inherited if certain conditions are met. In practice, this means that you do not need to write initializer overrides in many common scenarios, and can inherit your superclass initializers with minimal effort whenever it is safe to do so.

Assuming that you provide default values for any new properties you introduce in a subclass, the following two rules apply:

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 implementation 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 definition—then it automatically inherits all of the superclass convenience initializers.

These rules apply even if your subclass adds further convenience initializers.

NOTE

A subclass can implement a superclass designated initializer as a subclass convenience initializer as part of satisfying rule 2.

Designated and Convenience Initializers in Action

  • classFood {
  • varname: String
  • init(name: String) {
  • self.name = name
  • }
  • convenienceinit() {
  • self.init(name: “[Unnamed]“)
  • }
  • }

 

  • letnamedMeat = Food(name: “Bacon”)
  • // namedMeat’s name is “Bacon”

 

  • letmysteryMeat = Food()
  • // mysteryMeat’s name is “[Unnamed]“

 

  • classRecipeIngredient: Food {
  • varquantity: Int
  • init(name: String, quantity: Int) {
  • self.quantity = quantity
  • super.init(name: name)
  • }
  • overrideconvenienceinit(name: String) {
  • self.init(name: name, quantity: 1)
  • }
  • }

 

  • letoneMysteryItem = RecipeIngredient()
  • letoneBacon = RecipeIngredient(name: “Bacon”)
  • letsixEggs = RecipeIngredient(name: “Eggs”, quantity: 6)

 

  • classShoppingListItem: RecipeIngredient {
  • varpurchased = false
  • vardescription: String {
  • varoutput = “\(quantity) x \(name)”
  • output += purchased ? ” ✔” : ” ✘”
  • returnoutput
  • }
  • }
  • varbreakfastList = [
  • ShoppingListItem(),
  • ShoppingListItem(name: "Bacon"),
  • ShoppingListItem(name: "Eggs", quantity: 6),
  • ]
  • breakfastList[0].name = “Orange juice”
  • breakfastList[0].purchased = true
  • foriteminbreakfastList {
  • println(item.description)
  • }
  • // 1 x Orange juice ✔
  • // 1 x Bacon ✘
  • // 6 x Eggs ✘

Required Initializers

Write the required modifier before the definition of a class initializer to indicate that every subclass of the class must implement that initializer:

  • classSomeClass {
  • requiredinit() {
  • // initializer implementation goes here
  • }
  • }

 

  • classSomeSubclass: SomeClass {
  • requiredinit() {
  • // subclass implementation of the required initializer goes here
  • }
  • }
  • classSomeClass {
  • letsomeProperty: SomeType = {
  • // create a default value for someProperty inside this closure
  • // someValue must be of the same type as SomeType
  • returnsomeValue
  • }()
  • }

Setting a Default Property Value with a Closure or Function

 

  • structCheckerboard {
  • letboardColors: [Bool] = {
  • vartemporaryBoard = [Bool]()
  • varisBlack = false
  • foriin1…10 {
  • forjin1…10 {
  • temporaryBoard.append(isBlack)
  • isBlack = !isBlack
  • }
  • isBlack = !isBlack
  • }
  • returntemporaryBoard
  • }()
  • funcsquareIsBlackAtRow(row: Int, column: Int) -> Bool {
  • returnboardColors[(row * 10) + column]
  • }
  • }

 

  • letboard = Checkerboard()
  • println(board.squareIsBlackAtRow(0, column: 1))
  • // prints “true”
  • println(board.squareIsBlackAtRow(9, column: 9))
  • // prints “false”

 

Deinitialization

deinitializer is called immediately before a class instance is deallocated. You write deinitializers with thedeinit keyword, similar to how intializers are written with the init keyword. Deinitializers are only available on class types.

How Deinitialization Works

deinit {

  • // perform the deinitialization
  • }

Deinitializers are called automatically, just before instance deallocation takes place. You are not allowed to call a deinitializer yourself. Superclass deinitializers are inherited by their subclasses, and the superclass deinitializer is called automatically at the end of a subclass deinitializer implementation. Superclass deinitializers are always called, even if a subclass does not provide its own deinitializer.

Because an instance is not deallocated until after its deinitializer is called, a deinitializer can access all properties of the instance it is called on and can modify its behavior based on those properties (such as looking up the name of a file that needs to be closed).

Deinitializers in Action

  • structBank {
  • staticvarcoinsInBank = 10_000
  • staticfuncvendCoins(varnumberOfCoinsToVend: Int) -> Int {
  • numberOfCoinsToVend = min(numberOfCoinsToVend, coinsInBank)
  • coinsInBank -= numberOfCoinsToVend
  • returnnumberOfCoinsToVend
  • }
  • staticfuncreceiveCoins(coins: Int) {
  • coinsInBank += coins
  • }
  • }
  • classPlayer {
  • varcoinsInPurse: Int
  • init(coins: Int) {
  • coinsInPurse = Bank.vendCoins(coins)
  • }
  • funcwinCoins(coins: Int) {
  • coinsInPurse += Bank.vendCoins(coins)
  • }
  • deinit {
  • Bank.receiveCoins(coinsInPurse)
  • }
  • }

 

  • varplayerOne: Player? = Player(coins: 100)
  • println(“A new player has joined the game with \(playerOne!.coinsInPurse) coins”)
  • // prints “A new player has joined the game with 100 coins”
  • println(“There are now \(Bank.coinsInBank) coins left in the bank”)
  • // prints “There are now 9900 coins left in the bank”

 

  • playerOne!.winCoins(2_000)
  • println(“PlayerOne won 2000 coins & now has \(playerOne!.coinsInPurse) coins”)
  • // prints “PlayerOne won 2000 coins & now has 2100 coins”
  • println(“The bank now only has \(Bank.coinsInBank) coins left”)
  • // prints “The bank now only has 7900 coins left”

 

  • playerOne = nil
  • println(“PlayerOne has left the game”)
  • // prints “PlayerOne has left the game”
  • println(“The bank now has \(Bank.coinsInBank) coins”)
  • // prints “The bank now has 10000 coins”

 

Optional Chaining

On This Page

Optional chaining is a process for querying and calling properties, methods, and subscripts on an optional that might currently be nil. If the optional contains a value, the property, method, or subscript call succeeds; if the optional is nil, the property, method, or subscript call returns nil. Multiple queries can be chained together, and the entire chain fails gracefully if any link in the chain is nil.

Optional Chaining as an Alternative to Forced Unwrapping

You specify optional chaining by placing a question mark (?) after the optional value on which you wish to call a property, method or subscript if the optional is non-nil. This is very similar to placing an exclamation mark (!) after an optional value to force the unwrapping of its value. The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.

To reflect the fact that optional chaining can be called on a nil value, the result of an optional chaining call is always an optional value, even if the property, method, or subscript you are querying returns a non-optional value. You can use this optional return value to check whether the optional chaining call was successful (the returned optional contains a value), or did not succeed due to a nil value in the chain (the returned optional value is nil).

  • classPerson {
  • varresidence: Residence?
  • }
  • classResidence {
  • varnumberOfRooms = 1
  • }
  • letjohn = Person()

 

  • letroomCount = john.residence!.numberOfRooms
  • // this triggers a runtime error

 

  • ifletroomCount = john.residence?.numberOfRooms {
  • println(“John’s residence has \(roomCount) room(s).”)
  • } else {
  • println(“Unable to retrieve the number of rooms.”)
  • }
  • // prints “Unable to retrieve the number of rooms.”

 

  • ifletroomCount = john.residence?.numberOfRooms {
  • println(“John’s residence has \(roomCount) room(s).”)
  • } else {
  • println(“Unable to retrieve the number of rooms.”)
  • }
  • // prints “John’s residence has 1 room(s).”
  • classPerson {
  • varresidence: Residence?
  • }

Defining Model Classes for Optional Chaining

 

  • classResidence {
  • varrooms = [Room]()
  • varnumberOfRooms: Int {
  • returnrooms.count
  • }
  • subscript(i: Int) -> Room {
  • get {
  • returnrooms[i]
  • }
  • set {
  • rooms[i] = newValue
  • }
  • }
  • funcprintNumberOfRooms() {
  • println(“The number of rooms is \(numberOfRooms)”)
  • }
  • varaddress: Address?
  • }

 

  • classRoom {
  • letname: String
  • init(name: String) { self.name = name }
  • }

 

  • classAddress {
  • varbuildingName: String?
  • varbuildingNumber: String?
  • varstreet: String?
  • funcbuildingIdentifier() -> String? {
  • ifbuildingName != nil {
  • returnbuildingName
  • } else if buildingNumber != nil {
  • returnbuildingNumber
  • } else {
  • returnnil
  • }
  • }
  • }
  • letjohn = Person()
  • ifletroomCount = john.residence?.numberOfRooms {
  • println(“John’s residence has \(roomCount) room(s).”)
  • } else {
  • println(“Unable to retrieve the number of rooms.”)
  • }
  • // prints “Unable to retrieve the number of rooms.”

 

Accessing Properties Through Optional Chaining

 

  • letsomeAddress = Address()
  • someAddress.buildingNumber = “29”
  • someAddress.street = “Acacia Road”
  • john.residence?.address = someAddress
  • funcprintNumberOfRooms() {
  • println(“The number of rooms is \(numberOfRooms)”)
  • }

Calling Methods Through Optional Chaining

 

  • ifjohn.residence?.printNumberOfRooms() != nil {
  • println(“It was possible to print the number of rooms.”)
  • } else {
  • println(“It was not possible to print the number of rooms.”)
  • }
  • // prints “It was not possible to print the number of rooms.”

 

  • if (john.residence?.address = someAddress) != nil {
  • println(“It was possible to set the address.”)
  • } else {
  • println(“It was not possible to set the address.”)
  • }
  • // prints “It was not possible to set the address.”
  • ifletfirstRoomName = john.residence?[0].name {
  • println(“The first room name is \(firstRoomName).”)
  • } else {
  • println(“Unable to retrieve the first room name.”)
  • }
  • // prints “Unable to retrieve the first room name.”
  • john.residence?[0] = Room(name: “Bathroom”)

Accessing Subscripts Through Optional Chaining

 

  • letjohnsHouse = Residence()
  • johnsHouse.rooms.append(Room(name: “Living Room”))
  • johnsHouse.rooms.append(Room(name: “Kitchen”))
  • john.residence = johnsHouse
  • ifletfirstRoomName = john.residence?[0].name {
  • println(“The first room name is \(firstRoomName).”)
  • } else {
  • println(“Unable to retrieve the first room name.”)
  • }
  • // prints “The first room name is Living Room.”
  • vartestScores = [“Dave”: [86, 82, 84], “Tim”: [79, 94, 81]]
  • testScores["Dave"]?[0] = 91
  • testScores["Tim"]?[0]++
  • testScores["Brian"]?[0] = 72
  • // the “Dave” array is now [91, 82, 84] and the “Tim” array is now [80, 94, 81]

Accessing Subscripts of Optional Type

Linking Multiple Levels of Chaining

You can link together multiple levels of optional chaining to drill down to properties, methods, and subscripts deeper within a model. However, multiple levels of optional chaining do not add more levels of optionality to the returned value.

To put it another way:

  • If the type you are trying to retrieve is not optional, it will become optional because of the optional chaining.
  • If the type you are trying to retrieve isalready optional, it will not become more optional because of the chaining.

Therefore:

  • If you try to retrieve anInt value through optional chaining, an Int? is always returned, no matter how many levels of chaining are used.
  • Similarly, if you try to retrieve anInt? value through optional chaining, an Int? is always returned, no matter how many levels of chaining are used.
  • ifletjohnsStreet = john.residence?.address?.street {
  • println(“John’s street name is \(johnsStreet).”)
  • } else {
  • println(“Unable to retrieve the address.”)
  • }
  • // prints “Unable to retrieve the address.”

 

  • letjohnsAddress = Address()
  • johnsAddress.buildingName = “The Larches”
  • johnsAddress.street = “Laurel Street”
  • john.residence!.address = johnsAddress

 

  • ifletjohnsStreet = john.residence?.address?.street {
  • println(“John’s street name is \(johnsStreet).”)
  • } else {
  • println(“Unable to retrieve the address.”)
  • }
  • // prints “John’s street name is Laurel Street.”
  • ifletbuildingIdentifier = john.residence?.address?.buildingIdentifier() {
  • println(“John’s building identifier is \(buildingIdentifier).”)
  • }
  • // prints “John’s building identifier is The Larches.”

Chaining on Methods With Optional Return Values

 

  • ifletbeginsWithThe =
  • john.residence?.address?.buildingIdentifier()?.hasPrefix(“The”) {
  • ifbeginsWithThe {
  • println(“John’s building identifier begins with \”The\”.”)
  • } else {
  • println(“John’s building identifier does not begin with \”The\”.”)
  • }
  • }
  • // prints “John’s building identifier begins with “The”.”

 

Type Casting

Type casting is a way to check the type of an instance, and/or to treat that instance as if it is a different superclass or subclass from somewhere else in its own class hierarchy.

Type casting in Swift is implemented with the is and as operators. These two operators provide a simple and expressive way to check the type of a value or cast a value to a different type.

Defining a Class Hierarchy for Type Casting

You can use type casting with a hierarchy of classes and subclasses to check the type of a particular class instance and to cast that instance to another class within the same hierarchy. The three code snippets below define a hierarchy of classes and an array containing instances of those classes, for use in an example of type casting.

  • classMediaItem {
  • varname: String
  • init(name: String) {
  • self.name = name
  • }
  • }

 

  • classMovie: MediaItem {
  • vardirector: String
  • init(name: String, director: String) {
  • self.director = director
  • super.init(name: name)
  • }
  • }
  • classSong: MediaItem {
  • varartist: String
  • init(name: String, artist: String) {
  • self.artist = artist
  • super.init(name: name)
  • }
  • }

 

  • letlibrary = [
  • Movie(name: "Casablanca", director: "Michael Curtiz"),
  • Song(name: "Blue Suede Shoes", artist: "Elvis Presley"),
  • 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 type of “library” is inferred to be [MediaItem]

Checking Type

Use the type check operator (is) to check whether an instance is of a certain subclass type. The type check operator returns true if the instance is of that subclass type and false if it is not.

  • varmovieCount = 0
  • varsongCount = 0
  • foriteminlibrary {
  • ifitemisMovie {
  • ++movieCount
  • } else if item is Song {
  • ++songCount
  • }
  • }
  • println(“Media library contains \(movieCount) movies and \(songCount) songs”)
  • // prints “Media library contains 2 movies and 3 songs”

Downcasting

A constant or variable of a certain class type may actually refer to an instance of a subclass behind the scenes. Where you believe this is the case, you can try to downcast to the subclass type with the type cast operator (as).

Because downcasting can fail, the type cast operator comes in two different forms. The optional form, as?, returns an optional value of the type you are trying to downcast to. The forced form, as, attempts the downcast and force-unwraps the result as a single compound action.

Use the optional form of the type cast operator (as?) when you are not sure if the downcast will succeed. This form of the operator will always return an optional value, and the value will be nil if the downcast was not possible. This enables you to check for a successful downcast.

Use the forced form of the type cast operator (as) only when you are sure that the downcast will always succeed. This form of the operator will trigger a runtime error if you try to downcast to an incorrect class type.

 

  • foriteminlibrary {
  • ifletmovie = itemas? Movie {
  • println(“Movie: ‘\(movie.name)’, dir. \(movie.director)”)
  • } else if let song = item as? Song {
  • println(“Song: ‘\(song.name)’, by \(song.artist)”)
  • }
  • }
  • // Movie: ‘Casablanca’, dir. Michael Curtiz
  • // Song: ‘Blue Suede Shoes’, by Elvis Presley
  • // Movie: ‘Citizen Kane’, dir. Orson Welles
  • // Song: ‘The One And Only’, by Chesney Hawkes
  • // Song: ‘Never Gonna Give You Up’, by Rick Astley

Type Casting for Any and AnyObject

Swift provides two special type aliases for working with non-specific types:

  • AnyObjectcan represent an instance of any class type.
  • Anycan represent an instance of any type at all, apart from function types.

AnyObject

When working with Cocoa APIs, it is common to receive an array with a type of [AnyObject], or “an array of values of any object type”. This is because Objective-C does not have explicitly typed arrays. However, you can often be confident about the type of objects contained in such an array just from the information you know about the API that provided the array.

In these situations, you can use the forced version of the type cast operator (as) to downcast each item in the array to a more specific class type than AnyObject, without the need for optional unwrapping.

The example below defines an array of type [AnyObject] and populates this array with three instances of theMovie class:

  • letsomeObjects: [AnyObject] = [
  • Movie(name: "2001: A Space Odyssey", director: "Stanley Kubrick"),
  • Movie(name: "Moon", director: "Duncan Jones"),
  • Movie(name: "Alien", director: "Ridley Scott")
  • ]

Because this array is known to contain only Movie instances, you can downcast and unwrap directly to a non-optional Movie with the forced version of the type cast operator (as):

  • forobjectinsomeObjects {
  • letmovie = objectasMovie
  • println(“Movie: ‘\(movie.name)’, dir. \(movie.director)”)
  • }
  • // Movie: ‘2001: A Space Odyssey’, dir. Stanley Kubrick
  • // Movie: ‘Moon’, dir. Duncan Jones
  • // Movie: ‘Alien’, dir. Ridley Scott

For an even shorter form of this loop, downcast the someObjects array to a type of [Movie] instead of downcasting each item:

  • formovieinsomeObjectsas [Movie] {
  • println(“Movie: ‘\(movie.name)’, dir. \(movie.director)”)
  • }
  • // Movie: ‘2001: A Space Odyssey’, dir. Stanley Kubrick
  • // Movie: ‘Moon’, dir. Duncan Jones
  • // Movie: ‘Alien’, dir. Ridley Scott

Any

Here’s an example of using Any to work with a mix of different types, including non-class types. The example creates an array called things, which can store values of type Any:

  • varthings = [Any]()
  • things.append(0)
  • things.append(0)
  • things.append(42)
  • things.append(14159)
  • things.append(“hello”)
  • things.append((0, 5.0))
  • things.append(Movie(name: “Ghostbusters”, director: “Ivan Reitman”))

 

  • forthinginthings {
  • switchthing {
  • case0asInt:
  • println(“zero as an Int”)
  • case0asDouble:
  • println(“zero as a Double”)
  • caseletsomeIntasInt:
  • println(“an integer value of \(someInt)”)
  • caseletsomeDoubleasDoublewheresomeDouble > 0:
  • println(“a positive double value of \(someDouble)”)
  • caseisDouble:
  • println(“some other double value that I don’t want to print”)
  • caseletsomeStringasString:
  • println(“a string value of \”\(someString)\””)
  • caselet (x, y) as (Double, Double):
  • println(“an (x, y) point at \(x), \(y)”)
  • caseletmovieasMovie:
  • println(“a movie called ‘\(movie.name)’, dir. \(movie.director)”)
  • default:
  • println(“something else”)
  • }
  • }
  • // zero as an Int
  • // zero as a Double
  • // an integer value of 42
  • // a positive double value of 3.14159
  • // a string value of “hello”
  • // an (x, y) point at 3.0, 5.0
  • // a movie called ‘Ghostbusters’, dir. Ivan Reitman

 

Nested Types

Enumerations are often created to support a specific class or structure’s functionality. Similarly, it can be convenient to define utility classes and structures purely for use within the context of a more complex type. To accomplish this, Swift enables you to define nested types, whereby you nest supporting enumerations, classes, and structures within the definition of the type they support.

To nest a type within another type, write its definition within the outer braces of the type it supports. Types can be nested to as many levels as are required.

Nested Types in Action

  • structBlackjackCard {
  • // nested Suit enumeration
  • enumSuit: Character {
  • caseSpades = “♠”, Hearts = “♡”, Diamonds = “♢”, Clubs = “♣”
  • }
  • // nested Rank enumeration
  • enumRank: Int {
  • caseTwo = 2, Three, Four, Five, Six, Seven, Eight, Nine, Ten
  • caseJack, Queen, King, Ace
  • structValues {
  • letfirst: Int, second: Int?
  • }
  • varvalues: Values {
  • switchself {
  • case .Ace:
  • returnValues(first: 1, second: 11)
  • case .Jack, .Queen, .King:
  • returnValues(first: 10, second: nil)
  • default:
  • returnValues(first: self.toRaw(), second: nil)
  • }
  • }
  • }
  • // BlackjackCard properties and methods
  • letrank: Rank, suit: Suit
  • vardescription: String {
  • varoutput = “suit is \(suit.toRaw()),”
  • output += ” value is \(rank.values.first)”
  • ifletsecond = rank.values.second {
  • output += ” or \(second)”
  • }
  • returnoutput
  • }
  • }

 

  • lettheAceOfSpades = BlackjackCard(rank: .Ace, suit: .Spades)
  • println(“theAceOfSpades: \(theAceOfSpades.description)”)
  • // prints “theAceOfSpades: suit is ♠, value is 1 or 11″

Referring to Nested Types

To use a nested type outside of its definition context, prefix its name with the name of the type it is nested within:

  • letheartsSymbol = BlackjackCard.Suit.Hearts.toRaw()
  • // heartsSymbol is “♡”

 

Extensions

Extensions add new functionality to an existing class, structure, or enumeration type. This includes the ability to extend types for which you do not have access to the original source code (known as retroactive modeling).

Extensions in Swift can:

  • Add computed properties and computed static properties
  • Define instance methods and type methods
  • Provide new initializers
  • Define subscripts
  • Define and use new nested types
  • Make an existing type conform to a protocol

 

Extension Syntax

Declare extensions with the extension keyword:

  • extensionSomeType {
  • // new functionality to add to SomeType goes here
  • }

An extension can extend an existing type to make it adopt one or more protocols. Where this is the case, the protocol names are written in exactly the same way as for a class or structure:

  • extensionSomeType: SomeProtocol, AnotherProtocol {
  • // implementation of protocol requirements goes here
  • }

Computed Properties

Extensions can add computed instance properties and computed type properties to existing types.

  • extensionDouble {
  • varkm: Double { returnself * 0 }
  • varm: Double { returnself }
  • varcm: Double { returnself / 0 }
  • varmm: Double { returnself / 0 }
  • varft: Double { returnself / 28084 }
  • }
  • letoneInch = 4.mm
  • println(“One inch is \(oneInch) meters”)
  • // prints “One inch is 0.0254 meters”
  • letthreeFeet = 3.ft
  • println(“Three feet is \(threeFeet) meters”)
  • // prints “Three feet is 0.914399970739201 meters”
  • letaMarathon = 42.km + 195.m
  • println(“A marathon is \(aMarathon) meters long”)
  • // prints “A marathon is 42195.0 meters long”

Initializers

Extensions can add new initializers to existing types. This enables you to extend other types to accept your own custom types as initializer parameters, or to provide additional initialization options that were not included as part of the type’s original implementation.

Extensions can add new convenience initializers to a class, but they cannot add new designated initializers or deinitializers to a class. Designated initializers and deinitializers must always be provided by the original class implementation.

  • structSize {
  • varwidth = 0, height = 0.0
  • }
  • structPoint {
  • varx = 0, y = 0.0
  • }
  • structRect {
  • varorigin = Point()
  • varsize = Size()
  • }

 

  • letdefaultRect = Rect()
  • letmemberwiseRect = Rect(origin: Point(x: 0, y: 2.0),
  • size: Size(width: 0, height: 5.0))

 

  • extensionRect {
  • init(center: Point, size: Size) {
  • letoriginX = center.x – (size.width / 2)
  • letoriginY = center.y – (size.height / 2)
  • self.init(origin: Point(x: originX, y: originY), size: size)
  • }
  • }
  • letcenterRect = Rect(center: Point(x: 0, y: 4.0),
  • size: Size(width: 0, height: 3.0))
  • // centerRect’s origin is (2.5, 2.5) and its size is (3.0, 3.0)

Methods

Extensions can add new instance methods and type methods to existing types.

  • extensionInt {
  • funcrepetitions(task: () -> ()) {
  • foriin0..<self {
  • task()
  • }
  • }
  • }

 

  • 3.repetitions({
  • println(“Hello!”)
  • })
  • // Hello!
  • // Hello!
  • // Hello!

 

  • 3.repetitions {
  • println(“Goodbye!”)
  • }
  • // Goodbye!
  • // Goodbye!
  • // Goodbye!

Mutating Instance Methods

Instance methods added with an extension can also modify (or mutate) the instance itself. Structure and enumeration methods that modify self or its properties must mark the instance method as mutating, just like mutating methods from an original implementation.

  • extensionInt {
  • mutatingfuncsquare() {
  • self = self * self
  • }
  • }
  • varsomeInt = 3
  • someInt.square()
  • // someInt is now 9

Subscripts

Extensions can add new subscripts to an existing type.

 

  • extensionInt {
  • subscript(vardigitIndex: Int) -> Int {
  • vardecimalBase = 1
  • whiledigitIndex > 0 {
  • decimalBase *= 10
  • –digitIndex
  • }
  • return (self / decimalBase) % 10
  • }
  • }
  • 746381295[0]
  • // returns 5
  • 746381295[1]
  • // returns 9
  • 746381295[2]
  • // returns 2
  • 746381295[8]
  • // returns 7
  • 746381295[9]
  • // returns 0, as if you had requested:
  • 0746381295[9]

Nested Types

Extensions can add new nested types to existing classes, structures and enumerations:

  • extensionInt {
  • enumKind {
  • caseNegative, Zero, Positive
  • }
  • varkind: Kind {
  • switchself {
  • case0:
  • return .Zero
  • caseletxwherex > 0:
  • return .Positive
  • default:
  • return .Negative
  • }
  • }
  • }

 

  • funcprintIntegerKinds(numbers: [Int]) {
  • fornumberinnumbers {
  • switchnumber.kind {
  • case .Negative:
  • print(“- “)
  • case .Zero:
  • print(“0 “)
  • case .Positive:
  • print(“+ “)
  • }
  • }
  • print(“\n”)
  • }
  • printIntegerKinds([3, 19, -27, 0, -6, 0, 7])
  • // prints “+ + – 0 – 0 +”

 

Protocols

 

protocol defines a blueprint of methods, properties, and other requirements that suit a particular task or piece of functionality. The protocol doesn’t actually provide an implementation for any of these requirements—it only describes what an implementation will look like. The protocol can then be adopted by a class, structure, or enumeration to provide an actual implementation of those requirements. Any type that satisfies the requirements of a protocol is said to conform to that protocol.

Protocols can require that conforming types have specific instance properties, instance methods, type methods, operators, and subscripts.

Protocol Syntax

You define protocols in a very similar way to classes, structures, and enumerations:

  • protocolSomeProtocol {
  • // protocol definition goes here
  • }

Custom types state that they adopt a particular protocol by placing the protocol’s name after the type’s name, separated by a colon, as part of their definition. Multiple protocols can be listed, and are separated by commas:

  • structSomeStructure: 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:

  • classSomeClass: SomeSuperclass, FirstProtocol, AnotherProtocol {
  • // class definition goes here
  • }

Property Requirements

A protocol can require any conforming type to provide an instance property or type property with a particular name and type. The protocol doesn’t specify whether the property should be a stored property or a computed property—it only specifies the required property name and type. The protocol also specifies whether each property must be gettable or gettable and settable.

If a protocol requires a property to be gettable and settable, that property requirement cannot be fulfilled by a constant stored property or a read-only computed property. If the protocol only requires a property to be gettable, the requirement can be satisfied by any kind of property, and it is valid for it also to be settable if this is useful for your own code.

Property requirements are always declared as variable properties, prefixed with the var keyword. Gettable and settable properties are indicated by writing { get set } after their type declaration, and gettable properties are indicated by writing { get }.

  • protocolSomeProtocol {
  • varmustBeSettable: Int { getset }
  • vardoesNotNeedToBeSettable: Int { get }
  • }

Always prefix type property requirements with the class keyword when you define them in a protocol. This is true even though type property requirements are prefixed with the static keyword when implemented by a structure or enumeration:

  • protocolAnotherProtocol {
  • classvarsomeTypeProperty: Int { getset }
  • }

Here’s an example of a protocol with a single instance property requirement:

  • protocolFullyNamed {
  • varfullName: String { get }
  • }

 

  • structPerson: FullyNamed {
  • varfullName: String
  • }
  • letjohn = Person(fullName: “John Appleseed”)
  • // john.fullName is “John Appleseed”

 

  • classStarship: FullyNamed {
  • varprefix: String?
  • varname: String
  • init(name: String, prefix: String? = nil) {
  • self.name = name
  • self.prefix = prefix
  • }
  • varfullName: String {
  • return (prefix != nil ? prefix! + ” ” : “”) + name
  • }
  • }
  • varncc1701 = Starship(name: “Enterprise”, prefix: “USS”)
  • // ncc1701.fullName is “USS Enterprise”

Method Requirements

Protocols can require specific instance methods and type methods to be implemented by conforming types. These methods are written as part of the protocol’s definition in exactly the same way as for normal instance and type methods, but without curly braces or a method body. Variadic parameters are allowed, subject to the same rules as for normal methods.

  • protocolSomeProtocol {
  • classfuncsomeTypeMethod()
  • }

 

  • protocolRandomNumberGenerator {
  • funcrandom() -> Double
  • }

 

  • classLinearCongruentialGenerator: RandomNumberGenerator {
  • varlastRandom = 0
  • letm = 0
  • leta = 0
  • letc = 0
  • funcrandom() -> Double {
  • lastRandom = ((lastRandom * a + c) % m)
  • returnlastRandom / m
  • }
  • }
  • letgenerator = LinearCongruentialGenerator()
  • println(“Here’s a random number: \(generator.random())”)
  • // prints “Here’s a random number: 0.37464991998171″
  • println(“And another one: \(generator.random())”)
  • // prints “And another one: 0.729023776863283″

Mutating Method Requirements

It is sometimes necessary for a method to modify (or mutate) the instance it belongs to. For instance methods on value types (that is, structures and enumerations) you place the mutating keyword before a method’s func keyword to indicate that the method is allowed to modify the instance it belongs to and/or any properties of that instance.

If you define a protocol instance method requirement that is intended to mutate instances of any type that adopts the protocol, mark the method with the mutating keyword as part of the protocol’s definition. This enables structures and enumerations to adopt the protocol and satisfy that method requirement.

  • protocolTogglable {
  • mutatingfunctoggle()
  • }

 

  • enumOnOffSwitch: Togglable {
  • caseOff, On
  • mutatingfunctoggle() {
  • switchself {
  • caseOff:
  • self = On
  • caseOn:
  • self = Off
  • }
  • }
  • }
  • varlightSwitch = OnOffSwitch.Off
  • lightSwitch.toggle()
  • // lightSwitch is now equal to .On

Protocols as Types

Protocols do not actually implement any functionality themselves. Nonetheless, any protocol you create will become a fully-fledged type for use in your code.

Because it is a type, you can use a protocol in many places where other types are allowed, including:

  • As a parameter type or return type in a function, method, or initializer
  • As the type of a constant, variable, or property
  • As the type of items in an array, dictionary, or other container
  • classDice {
  • letsides: Int
  • letgenerator: RandomNumberGenerator
  • init(sides: Int, generator: RandomNumberGenerator) {
  • self.sides = sides
  • self.generator = generator
  • }
  • funcroll() -> Int {
  • returnInt(generator.random() * Double(sides)) + 1
  • }
  • }

 

  • vard6 = Dice(sides: 6, generator: LinearCongruentialGenerator())
  • for_in1…5 {
  • println(“Random dice roll is \(d6.roll())”)
  • }
  • // Random dice roll is 3
  • // Random dice roll is 5
  • // Random dice roll is 4
  • // Random dice roll is 5
  • // Random dice roll is 4

Delegation

Delegation is a design pattern that enables a class or structure to hand off (or delegate) some of its responsibilities to an instance of another type. This design pattern is implemented by defining a protocol that encapsulates the delegated responsibilities, such that a conforming type (known as a delegate) is guaranteed to provide the functionality that has been delegated. Delegation can be used to respond to a particular action, or to retrieve data from an external source without needing to know the underlying type of that source.

 

  • protocolDiceGame {
  • vardice: Dice { get }
  • funcplay()
  • }
  • protocolDiceGameDelegate {
  • funcgameDidStart(game: DiceGame)
  • funcgame(game: DiceGame, didStartNewTurnWithDiceRolldiceRoll: Int)
  • funcgameDidEnd(game: DiceGame)
  • }

 

  • classSnakesAndLadders: DiceGame {
  • letfinalSquare = 25
  • letdice = Dice(sides: 6, generator: LinearCongruentialGenerator())
  • varsquare = 0
  • varboard: [Int]
  • init() {
  • board = [Int](count: finalSquare + 1, repeatedValue: 0)
  • board[03] = +08; board[06] = +11; board[09] = +09; board[10] = +02
  • board[14] = -10; board[19] = -11; board[22] = -02; board[24] = -08
  • }
  • vardelegate: DiceGameDelegate?
  • funcplay() {
  • square = 0
  • delegate?.gameDidStart(self)
  • gameLoop: whilesquare != finalSquare {
  • letdiceRoll = dice.roll()
  • delegate?.game(self, didStartNewTurnWithDiceRoll: diceRoll)
  • switchsquare + diceRoll {
  • casefinalSquare:
  • breakgameLoop
  • caseletnewSquarewherenewSquare > finalSquare:
  • continuegameLoop
  • default:
  • square += diceRoll
  • square += board[square]
  • }
  • }
  • delegate?.gameDidEnd(self)
  • }
  • }

 

  • classDiceGameTracker: DiceGameDelegate {
  • varnumberOfTurns = 0
  • funcgameDidStart(game: DiceGame) {
  • numberOfTurns = 0
  • ifgameisSnakesAndLadders {
  • println(“Started a new game of Snakes and Ladders”)
  • }
  • println(“The game is using a \(game.dice.sides)-sided dice”)
  • }
  • funcgame(game: DiceGame, didStartNewTurnWithDiceRolldiceRoll: Int) {
  • ++numberOfTurns
  • println(“Rolled a \(diceRoll)”)
  • }
  • funcgameDidEnd(game: DiceGame) {
  • println(“The game lasted for \(numberOfTurns) turns”)
  • }
  • }

 

  • lettracker = DiceGameTracker()
  • letgame = SnakesAndLadders()
  • game.delegate = tracker
  • game.play()
  • // Started a new game of Snakes and Ladders
  • // The game is using a 6-sided dice
  • // Rolled a 3
  • // Rolled a 5
  • // Rolled a 4
  • // Rolled a 5
  • // The game lasted for 4 turns

Adding Protocol Conformance with an Extension

You can extend an existing type to adopt and conform to a new protocol, even if you do not have access to the source code for the existing type. Extensions can add new properties, methods, and subscripts to an existing type, and are therefore able to add any requirements that a protocol may demand.

 

protocol TextRepresentable {

  • funcasText() -> String
  • }

The Dice class from earlier can be extended to adopt and conform to TextRepresentable:

  • extensionDice: TextRepresentable {
  • funcasText() -> String {
  • return”A \(sides)-sided dice”
  • }
  • }

 

  • letd12 = Dice(sides: 12, generator: LinearCongruentialGenerator())
  • println(d12.asText())
  • // prints “A 12-sided dice”

 

  • extensionSnakesAndLadders: TextRepresentable {
  • funcasText() -> String {
  • return”A game of Snakes and Ladders with \(finalSquare) squares”
  • }
  • }
  • println(game.asText())
  • // prints “A game of Snakes and Ladders with 25 squares”

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:

  • structHamster {
  • varname: String
  • funcasText() -> String {
  • return”A hamster named \(name)”
  • }
  • }
  • extensionHamster: TextRepresentable {}

 

  • letsimonTheHamster = Hamster(name: “Simon”)
  • letsomethingTextRepresentable: TextRepresentable = simonTheHamster
  • println(somethingTextRepresentable.asText())
  • // prints “A hamster named Simon”
  • letthings: [TextRepresentable] = [game, d12, simonTheHamster]

Collections of Protocol Types

 

  • forthinginthings {
  • println(thing.asText())
  • }
  • // A game of Snakes and Ladders with 25 squares
  • // A 12-sided dice
  • // A hamster named Simon

Protocol Inheritance

A protocol can inherit one or more other protocols and can add further requirements on top of the requirements it inherits

 

protocol InheritingProtocol: SomeProtocol, AnotherProtocol {

  • // protocol definition goes here
  • }

 

  • protocolPrettyTextRepresentable: TextRepresentable {
  • funcasPrettyText() -> String
  • }

 

  • extensionSnakesAndLadders: PrettyTextRepresentable {
  • funcasPrettyText() -> String {
  • varoutput = asText() + “:\n”
  • forindexin1…finalSquare {
  • switchboard[index] {
  • caseletladderwhereladder > 0:
  • output += “▲ “
  • caseletsnakewheresnake < 0:
  • output += “▼ “
  • default:
  • output += “○ “
  • }
  • }
  • returnoutput
  • }
  • }

 

  • println(game.asPrettyText())
  • // A game of Snakes and Ladders with 25 squares:
  • // ○ ○ ▲ ○ ○ ▲ ○ ○ ▲ ▲ ○ ○ ○ ▼ ○ ○ ○ ○ ▼ ○ ○ ▼ ○ ▼ ○

Protocol Composition

It can be useful to require a type to conform to multiple protocols at once. You can combine multiple protocols into a single requirement with a protocol composition. Protocol compositions have the formprotocol<SomeProtocol, AnotherProtocol>. You can list as many protocols within the pair of angle brackets (<>) as you need, separated by commas.

  • protocolNamed {
  • varname: String { get }
  • }
  • protocolAged {
  • varage: Int { get }
  • }
  • structPerson: Named, Aged {
  • varname: String
  • varage: Int
  • }
  • funcwishHappyBirthday(celebrator: protocol<Named, Aged>) {
  • println(“Happy birthday \(celebrator.name) – you’re \(celebrator.age)!”)
  • }
  • letbirthdayPerson = Person(name: “Malcolm”, age: 21)
  • wishHappyBirthday(birthdayPerson)
  • // prints “Happy birthday Malcolm – you’re 21!”

 

Checking for Protocol Conformance

You can use the is and as operators described in type casting to check for protocol conformance, and to cast to a specific protocol.

Checking for and casting to a protocol follows exactly the same syntax as checking for and casting to a type:

  • Theis operator returns true if an instance conforms to a protocol and returns false if it does not.
  • Theas? version of the downcast operator returns an optional value of the protocol’s type, and this value is nil if the instance does not conform to that protocol.
  • Theas version of the downcast operator forces the downcast to the protocol type and triggers a runtime error if the downcast does not succeed.

 

  • @objcprotocolHasArea {
  • vararea: Double { get }
  • }

 

  • classCircle: HasArea {
  • letpi = 1415927
  • varradius: Double
  • vararea: Double { returnpi * radius * radius }
  • init(radius: Double) { self.radius = radius }
  • }
  • classCountry: HasArea {
  • vararea: Double
  • init(area: Double) { self.area = area }
  • }

 

  • classAnimal {
  • varlegs: Int
  • init(legs: Int) { self.legs = legs }
  • }
  • letobjects: [AnyObject] = [
  • Circle(radius: 0),
  • Country(area: 243_610),
  • Animal(legs: 4)
  • ]

 

  • forobjectinobjects {
  • ifletobjectWithArea = objectas? HasArea {
  • println(“Area is \(objectWithArea.area)”)
  • } else {
  • println(“Something that doesn’t have an area”)
  • }
  • }
  • // Area is 12.5663708
  • // Area is 243610.0
  • // Something that doesn’t have an area

Optional Protocol Requirements

You can define optional requirements for protocols, These requirements do not have to be implemented by types that conform to the protocol. Optional requirements are prefixed by the optional modifier as part of the protocol’s definition.

An optional protocol requirement can be called with optional chaining, to account for the possibility that the requirement was not implemented by a type that conforms to the protocol.

@objc protocol CounterDataSource {

  • optionalfuncincrementForCount(count: Int) -> Int
  • optionalvarfixedIncrement: Int { get }
  • }

 

  • @objcclassCounter {
  • varcount = 0
  • vardataSource: CounterDataSource?
  • funcincrement() {
  • ifletamount = dataSource?.incrementForCount?(count) {
  • count += amount
  • } else if let amount = dataSource?.fixedIncrement? {
  • count += amount
  • }
  • }
  • }

 

  • classThreeSource: CounterDataSource {
  • letfixedIncrement = 3
  • }

 

  • varcounter = Counter()
  • counter.dataSource = ThreeSource()
  • for_in1…4 {
  • counter.increment()
  • println(counter.count)
  • }
  • // 3
  • // 6
  • // 9
  • // 12

 

  • classTowardsZeroSource: CounterDataSource {
  • funcincrementForCount(count: Int) -> Int {
  • ifcount == 0 {
  • return0
  • } else if count < 0 {
  • return1
  • } else {
  • return -1
  • }
  • }
  • }

 

  • counter.count = -4
  • counter.dataSource = TowardsZeroSource()
  • for_in1…5 {
  • counter.increment()
  • println(counter.count)
  • }
  • // -3
  • // -2
  • // -1
  • // 0
  • // 0

 

Generics

Generic code enables you to write flexible, reusable functions and types that can work with any type, subject to requirements that you define. You can write code that avoids duplication and expresses its intent in a clear, abstracted manner.

Generics are one of the most powerful features of Swift, and much of the Swift standard library is built with generic code.

The Problem That Generics Solve

  • funcswapTwoInts(inouta: Int, inoutb: Int) {
  • lettemporaryA = a
  • a = b
  • b = temporaryA
  • }

 

  • varsomeInt = 3
  • varanotherInt = 107
  • swapTwoInts(&someInt, &anotherInt)
  • println(“someInt is now \(someInt), and anotherInt is now \(anotherInt)”)
  • // prints “someInt is now 107, and anotherInt is now 3″

 

  • funcswapTwoStrings(inouta: String, inoutb: String) {
  • lettemporaryA = a
  • a = b
  • b = temporaryA
  • }
  • funcswapTwoDoubles(inouta: Double, inoutb: Double) {
  • lettemporaryA = a
  • a = b
  • b = temporaryA
  • }

Generic Functions

Generic functions can work with any type.

func swapTwoValues<T>(inout a: T, inout b: T) {

  • lettemporaryA = a
  • a = b
  • b = temporaryA
  • }

 

  • funcswapTwoInts(inouta: Int, inoutb: Int)
  • funcswapTwoValues<T>(inouta: T, inoutb: T)

 

  • varsomeInt = 3
  • varanotherInt = 107
  • swapTwoValues(&someInt, &anotherInt)
  • // someInt is now 107, and anotherInt is now 3
  • varsomeString = “hello”
  • varanotherString = “world”
  • swapTwoValues(&someString, &anotherString)
  • // someString is now “world”, and anotherString is now “hello”

 

Type Parameters

Type parameters specify and name a placeholder type, and are written immediately after the function’s name, between a pair of matching angle brackets (such as <T>).

Once specified, a type parameter can be used to define the type of a function’s parameters (such as the aand b parameters of the swapTwoValues function); or as the function’s return type; or as a type annotation within the body of the function. In each case, the placeholder type represented by the type parameter is replaced with an actual type whenever the function is called.

You can provide more than one type parameter by writing multiple type parameter names within the angle brackets, separated by commas.

Naming Type Parameters

In simple cases where a generic function or generic type needs to refer to a single placeholder type (such as the swapTwoValues generic function above, or a generic collection that stores a single type, such as Array), it is traditional to use the single-character name T for the type parameter. However, you can use any valid identifier as the type parameter name.

If you are defining more complex generic functions, or generic types with multiple parameters, it can be useful to provide more descriptive type parameter names. For example, Swift’s Dictionary type has two type parameters—one for its keys and one for its values. If you were writing Dictionary yourself, you might name these two type parameters KeyType and ValueType to remind you of their purpose as you use them within your generic code.

 

Generic Types

In addition to generic functions, Swift enables you to define your own generic types. These are custom classes, structures, and enumerations that can work with any type, in a similar way to Array and Dictionary.

This section shows you how to write a generic collection type called Stack.

The illustration below shows the push / pop behavior for a stack:

 

  1. There are currently three values on the stack.
  2. A fourth value is “pushed” on to the top of the stack.
  3. The stack now holds four values, with the most recent one at the top.
  4. The top item in the stack is removed, or “popped”.
  5. After popping a value, the stack once again holds three values.

Here’s how to write a non-generic version of a stack, in this case for a stack of Int values:

  • structIntStack {
  • varitems = [Int]()
  • mutatingfuncpush(item: Int) {
  • items.append(item)
  • }
  • mutatingfuncpop() -> Int {
  • returnitems.removeLast()
  • }
  • }
  • varitems = [T]()
  • mutatingfuncpush(item: T) {
  • items.append(item)
  • }
  • mutatingfuncpop() -> T {
  • returnitems.removeLast()
  • }
  • }

structStack<T> {

This future type can be referred to as “T” anywhere within the structure’s definition. In this case, T is used as a placeholder in three places:

  • To create a property calleditems, which is initialized with an empty array of values of type T
  • To specify that thepush method has a single parameter called item, which must be of type T
  • To specify that the value returned by thepop method will be a value of type T
  • varstackOfStrings = Stack<String>()
  • stackOfStrings.push(“uno”)
  • stackOfStrings.push(“dos”)
  • stackOfStrings.push(“tres”)
  • stackOfStrings.push(“cuatro”)
  • // the stack now contains 4 strings

 

  • letfromTheTop = stackOfStrings.pop()
  • // fromTheTop is equal to “cuatro”, and the stack now contains 3 strings

Extending a Generic Type

When you extend a generic type, you do not provide a type parameter list as part of the extension’s definition. Instead, the type parameter list from the original type definition is available within the body of the extension, and the original type parameter names are used to refer to the type parameters from the original definition.

  • extensionStack {
  • vartopItem: T? {
  • returnitems.isEmpty ? nil : items[items.count - 1]
  • }
  • }

 

  • iflettopItem = stackOfStrings.topItem {
  • println(“The top item on the stack is \(topItem).”)
  • }
  • // prints “The top item on the stack is tres.”

Type Constraints

The swapTwoValues function and the Stack type can work with any type. However, it is sometimes useful to enforce certain type constraints on the types that can be used with generic functions and generic types. Type constraints specify that a type parameter must inherit from a specific class, or conform to a particular protocol or protocol composition.

Type Constraint Syntax

You write type constraints by placing a single class or protocol constraint after a type parameter’s name, separated by a colon, as part of the type parameter list. The basic syntax for type constraints on a generic function is shown below (although the syntax is the same for generic types):

  • funcsomeFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
  • // function body goes here
  • }
  • funcfindStringIndex(array: [String], valueToFind: String) -> Int? {
  • for (index, value) inenumerate(array) {
  • ifvalue == valueToFind {
  • returnindex
  • }
  • }
  • returnnil
  • }

Type Constraints in Action

 

  • letstrings = ["cat", "dog", "llama", "parakeet", "terrapin"]
  • ifletfoundIndex = findStringIndex(strings, “llama”) {
  • println(“The index of llama is \(foundIndex)”)
  • }
  • // prints “The index of llama is 2″

 

  • funcfindIndex<T>(array: [T], valueToFind: T) -> Int? {
  • for (index, value) inenumerate(array) {
  • ifvalue == valueToFind {
  • returnindex
  • }
  • }
  • returnnil
  • }

This function does not compile as written above. The problem lies with the equality check, “if value == valueToFind”. Not every type in Swift can be compared with the equal to operator (==). If you create your own class or structure to represent a complex data model, for example, then the meaning of “equal to” for that class or structure is not something that Swift can guess for you. Because of this, it is not possible to guarantee that this code will work for every possible type T, and an appropriate error is reported when you try to compile the code.

All is not lost, however. The Swift standard library defines a protocol called Equatable, which requires any conforming type to implement the equal to operator (==) and the not equal to operator (!=) to compare any two values of that type. All of Swift’s standard types automatically support the Equatable protocol.

Any type that is Equatable can be used safely with the findIndex function, because it is guaranteed to support the equal to operator. To express this fact, you write a type constraint of Equatable as part of the type parameter’s definition when you define the function:

  • funcfindIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
  • for (index, value) inenumerate(array) {
  • ifvalue == valueToFind {
  • returnindex
  • }
  • }
  • returnnil
  • }

 

  • letdoubleIndex = findIndex([14159, 0.1, 0.25], 9.3)
  • // doubleIndex is an optional Int with no value, because 9.3 is not in the array
  • letstringIndex = findIndex(["Mike", "Malcolm", "Andrea"], “Andrea”)
  • // stringIndex is an optional Int containing a value of 2

Associated Types

When defining a protocol, it is sometimes useful to declare one or more associated types as part of the protocol’s definition. An associated type gives a placeholder name (or alias) to a type that is used as part of the protocol. The actual type to use for that associated type is not specified until the protocol is adopted. Associated types are specified with the typealias keyword.

Associated Types in Action

  • protocolContainer {
  • typealiasItemType
  • mutatingfuncappend(item: ItemType)
  • varcount: Int { get }
  • subscript(i: Int) -> ItemType { get }
  • }

The Container protocol defines three required capabilities that any container must provide:

  • It must be possible to add a new item to the container with anappend
  • It must be possible to access a count of the items in the container through acount property that returns an Int
  • It must be possible to retrieve each item in the container with a subscript that takes anInt index value.

 

  • structIntStack: Container {
  • // original IntStack implementation
  • varitems = [Int]()
  • mutatingfuncpush(item: Int) {
  • items.append(item)
  • }
  • mutatingfuncpop() -> Int {
  • returnitems.removeLast()
  • }
  • // conformance to the Container protocol
  • typealiasItemType = Int
  • mutatingfuncappend(item: Int) {
  • self.push(item)
  • }
  • varcount: Int {
  • returnitems.count
  • }
  • subscript(i: Int) -> Int {
  • returnitems[i]
  • }
  • }

 

  • structStack<T>: Container {
  • // original Stack<T> implementation
  • varitems = [T]()
  • mutatingfuncpush(item: T) {
  • items.append(item)
  • }
  • mutatingfuncpop() -> T {
  • returnitems.removeLast()
  • }
  • // conformance to the Container protocol
  • mutatingfuncappend(item: T) {
  • self.push(item)
  • }
  • varcount: Int {
  • returnitems.count
  • }
  • subscript(i: Int) -> T {
  • returnitems[i]
  • }
  • }
  • extensionArray: Container {}

Extending an Existing Type to Specify an Associated Type

Where Clauses

Type constraints, as described in type constraints, enable you to define requirements on the type parameters associated with a generic function or type.

It can also be useful to define requirements for associated types. You do this by defining where clauses as part of a type parameter list. A where clause enables you to require that an associated type conforms to a certain protocol, and/or that certain type parameters and associated types be the same. You write a where clause by placing the where keyword immediately after the list of type parameters, followed by one or more constraints for associated types, and/or one or more equality relationships between types and associated types.

  • funcallItemsMatch<
  • C1: Container, C2: Container
  • whereC1.ItemType == C2.ItemType, C1.ItemType: Equatable>
  • (someContainer: C1, anotherContainer: C2) -> Bool {
  • // check that both containers contain the same number of items
  • ifsomeContainer.count != anotherContainer.count {
  • returnfalse
  • }
  • // check each pair of items to see if they are equivalent
  • foriin0..<someContainer.count {
  • ifsomeContainer[i] != anotherContainer[i] {
  • returnfalse
  • }
  • }
  • // all items match, so return true
  • returntrue
  • }

 

  • varstackOfStrings = Stack<String>()
  • stackOfStrings.push(“uno”)
  • stackOfStrings.push(“dos”)
  • stackOfStrings.push(“tres”)
  • vararrayOfStrings = ["uno", "dos", "tres"]
  • ifallItemsMatch(stackOfStrings, arrayOfStrings) {
  • println(“All items match.”)
  • } else {
  • println(“Not all items match.”)
  • }
  • // prints “All items match.”

 

Access Control

Access control restricts access to parts of your code from code in other source files and modules. This feature enables you to hide the implementation details of your code, and to specify a preferred interface through which that code can be accessed and used.

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.

Access Levels

Swift provides three different access levels for entities within your code. These access levels are relative to the source file in which an entity is defined, and also relative to the module that source file belongs to.

  • Public accessenables entities to be used within any source file from their defining module, and also in a source file from another module that imports the defining module. You typically use public access when specifying the public interface to a framework.
  • Internal accessenables entities to be used within any source file from their defining module, but not in any source file outside of that module. You typically use internal access when defining an app’s or a framework’s internal structure.
  • Private accessrestricts the use of an entity to its own defining source file. Use private access to hide the implementation details of a specific piece of functionality.

Public access is the highest (least restrictive) access level and private access is the lowest (or most restrictive) access level.

Guiding Principle of Access Levels

Access levels in Swift follow an overall guiding principle: No entity can be defined in terms of another entity that has a lower (more restrictive) access level.

For example:

  • A public variable cannot be defined as having an internal or private type, because the type might not be available everywhere that the public variable is used.
  • A function cannot have a higher access level than its parameter types and return type, because the function could be used in situations where its constituent types are not available to the surrounding code.

The specific implications of this guiding principle for different aspects of the language are covered in detail below.

Default Access Levels

All entities in your code (with a few specific exceptions, as described later in this chapter) have a default access level of internal if you do not specify an explicit access level yourself. As a result, in many cases you do not need to specify an explicit access level in your code.

 

Access Control Syntax

Define the access level for an entity by placing one of the public, internal, or private modifiers before the entity’s introducer:

  • publicclassSomePublicClass {}
  • internalclassSomeInternalClass {}
  • privateclassSomePrivateClass {}
  • publicvarsomePublicVariable = 0
  • internalletsomeInternalConstant = 0
  • privatefuncsomePrivateFunction() {}

 

  • classSomeInternalClass {} // implicitly internal
  • varsomeInternalConstant = 0// implicitly internal
  • publicclassSomePublicClass { // explicitly public class
  • publicvarsomePublicProperty = 0// explicitly public class member
  • varsomeInternalProperty = 0// implicitly internal class member
  • privatefuncsomePrivateMethod() {} // explicitly private class member
  • }
  • classSomeInternalClass { // implicitly internal class
  • varsomeInternalProperty = 0// implicitly internal class member
  • privatefuncsomePrivateMethod() {} // explicitly private class member
  • }
  • privateclassSomePrivateClass { // explicitly private class
  • varsomePrivateProperty = 0// implicitly private class member
  • funcsomePrivateMethod() {} // implicitly private class member
  • }

Custom Types

Tuple Types

The access level for a tuple type is the most restrictive access level of all types used in that tuple. For example, if you compose a tuple from two different types, one with internal access and one with private access, the access level for that compound tuple type will be private.

Function Types

The access level for a function type is calculated as the most restrictive access level of the function’s parameter types and return type. You must specify the access level explicitly as part of the function’s definition if the function’s calculated access level does not match the contextual default.

 

  • funcsomeFunction() -> (SomeInternalClass, SomePrivateClass) {
  • // function implementation goes here
  • }

 

  • privatefuncsomeFunction() -> (SomeInternalClass, SomePrivateClass) {
  • // function implementation goes here
  • }

Enumeration Types

The individual cases of an enumeration automatically receive the same access level as the enumeration they belong to. You cannot specify a different access level for individual enumeration cases.

  • publicenumCompassPoint {
  • caseNorth
  • caseSouth
  • caseEast
  • caseWest
  • }

Raw Values and Associated Values

The types used for any raw values or associated values in an enumeration definition must have an access level at least as high as the enumeration’s access level. You cannot use a private type as the raw value type of an enumeration with an internal access level, for example.

Nested Types

Nested types defined within a private type have an automatic access level of private. Nested types defined within a public type or an internal type have an automatic access level of internal. If you want a nested type within a public type to be publicly available, you must explicitly declare the nested type as public.

Subclassing

You can subclass any class that can be accessed in the current access context. A subclass cannot have a higher access level than its superclass—for example, you cannot write a public subclass of an internal superclass.

In addition, you can override any class member (method, property, initializer, or subscript) that is visible in a certain access context.

  • publicclassA {
  • privatefuncsomeMethod() {}
  • }
  • internalclassB: A {
  • overrideinternalfuncsomeMethod() {}
  • }

 

  • publicclassA {
  • privatefuncsomeMethod() {}
  • }
  • internalclassB: A {
  • overrideinternalfuncsomeMethod() {
  • super.someMethod()
  • }
  • }

Constants, Variables, Properties, and Subscripts

A constant, variable, or property cannot be more public than its type. It is not valid to write a public property with a private type, for example. Similarly, a subscript cannot be more public than either its index type or return type.

  • privatevarprivateInstance = SomePrivateClass()

Getters and Setters

Getters and setters for constants, variables, properties, and subscripts automatically receive the same access level as the constant, variable, property, or subscript they belong to.

You can give a setter a lower access level than its corresponding getter, to restrict the read-write scope of that variable, property, or subscript.

struct TrackedString {

  • private(set)varnumberOfEdits = 0
  • varvalue: String = “” {
  • didSet {
  • numberOfEdits++
  • }
  • }
  • }

 

  • varstringToEdit = TrackedString()
  • stringToEdit.value = “This string will be tracked.”
  • stringToEdit.value += ” This edit will increment numberOfEdits.”
  • stringToEdit.value += ” So will this one.”
  • println(“The number of edits is \(stringToEdit.numberOfEdits)”)
  • // prints “The number of edits is 3″

Initializers

Custom initializers can be assigned an access level less than or equal to the type that they initialize. The only exception is for required initializers. A required initializer must have the same access level as the class it belongs to.

As with function and method parameters, the types of an initializer’s parameters cannot be more private than the initializer’s own access level.

Default Initializers

Swift provides a default initializer without any arguments for any structure or base class that provides default values for all of its properties and does not provide at least one initializer itself.

Default Memberwise Initializers for Structure Types

The default memberwise initializer for a structure type is considered private if any of the structure’s stored properties are private. Otherwise, the initializer has an access level of internal.

As with the default initializer above, if you want a public structure type to be initializable with a memberwise initializer when used in another module, you must provide a public memberwise initializer yourself as part of the type’s definition.

Protocols

If you want to assign an explicit access level to a protocol type, do so at the point that you define the protocol. This enables you to create protocols that can only be adopted within a certain access context.

The access level of each requirement within a protocol definition is automatically set to the same access level as the protocol. You cannot set a protocol requirement to a different access level than the protocol it supports. This ensures that all of the protocol’s requirements will be visible on any type that adopts the protocol.

NOTE

If you define a public protocol, the protocol’s requirements require a public access level for those requirements when they are implemented. This behavior is different from other types, where a public type definition implies an access level of internal for the type’s members.

Protocol Inheritance

If you define a new protocol that inherits from an existing protocol, the new protocol can have at most the same access level as the protocol it inherits from. You cannot write a public protocol that inherits from an internal protocol, for example.

Protocol Conformance

A type can conform to a protocol with a lower access level than the type itself. For example, you can define a public type that can be used in other modules, but whose conformance to an internal protocol can only be used within the internal protocol’s defining module.

The context in which a type conforms to a particular protocol is the minimum of the type’s access level and the protocol’s access level. If a type is public, but a protocol it conforms to is internal, the type’s conformance to that protocol is also internal.

When you write or extend a type to conform to a protocol, you must ensure that the type’s implementation of each protocol requirement has at least the same access level as the type’s conformance to that protocol. For example, if a public type conforms to an internal protocol, the type’s implementation of each protocol requirement must be at least “internal”.

Extensions

You can extend a class, structure, or enumeration in any access context in which the class, structure, or enumeration is available. Any type members added in an extension have the same default access level as type members declared in the original type being extended. For example, if you extend a public type, any new type members you add will have a default access level of internal.

Alternatively, you can mark an extension with an explicit access level modifier (for example, private extension) to set a new default access level for all members defined within the extension. This new default can still be overridden within the extension for individual type members.

Adding Protocol Conformance with an Extension

You cannot provide an explicit access level modifier for an extension if you are using that extension to add protocol conformance. Instead, the protocol’s own access level is used to provide the default access level for each protocol requirement implementation within the extension.

Generics

The access level for a generic type or generic function is the minimum of the access level of the generic type or function itself and the access level of any type constraints on its type parameters.

Type Aliases

Any type aliases you define are treated as distinct types for the purposes of access control. A type alias can have an access level less than or equal to the access level of the type it aliases. For example, a private type alias can alias a private, internal, or public type, but a public type alias cannot alias an internal or private type.

 

Advanced Operators

Swift provides several advanced operators that perform more complex value manipulation.

When you define your own structures, classes, and enumerations, it can be useful to provide your own implementations of the standard Swift operators for these custom types. Swift makes it easy to provide tailored implementations of these operators and to determine exactly what their behavior should be for each type you create.

You’re not just limited to the predefined operators. Swift gives you the freedom to define your own custom infix, prefix, postfix, and assignment operators, with custom precedence and associativity values. These operators can be used and adopted in your code just like any of the predefined operators, and you can even extend existing types to support the custom operators you define.

Bitwise Operators

Bitwise operators enable you to manipulate the individual raw data bits within a data structure. They are often used in low-level programming, such as graphics programming and device driver creation. Bitwise operators can also be useful when you work with raw data from external sources, such as encoding and decoding data for communication over a custom protocol.

Swift supports all of the bitwise operators found in C, as described below.

Bitwise NOT Operator

  • letinitialBits: UInt8 = 0b00001111
  • letinvertedBits = ~initialBits// equals 11110000
  • letfirstSixBits: UInt8 = 0b11111100
  • letlastSixBits: UInt8 = 0b00111111
  • letmiddleFourBits = firstSixBits & lastSixBits// equals 00111100
  • letsomeBits: UInt8 = 0b10110010
  • letmoreBits: UInt8 = 0b01011110
  • letcombinedbits = someBits | moreBits// equals 11111110
  • letfirstBits: UInt8 = 0b00010100
  • letotherBits: UInt8 = 0b00000101
  • letoutputBits = firstBits ^ otherBits// equals 00010001

Bitwise AND Operator

Bitwise OR Operator

Bitwise XOR Operator

Bitwise Left and Right Shift Operators

The bitwise left shift operator (<<) and bitwise right shift operator (>>) move all bits in a number to the left or the right by a certain number of places, according to the rules defined below.

Bitwise left and right shifts have the effect of multiplying or dividing an integer number by a factor of two. Shifting an integer’s bits to the left by one position doubles its value, whereas shifting it to the right by one position halves its value.

Shifting Behavior for Unsigned Integers

The bit-shifting behavior for unsigned integers is as follows:

  1. Existing bits are moved to the left or right by the requested number of places.
  2. Any bits that are moved beyond the bounds of the integer’s storage are discarded.
  3. Zeroes are inserted in the spaces left behind after the original bits are moved to the left or right.

 

  • letshiftBits: UInt8 = 4// 00000100 in binary
  • shiftBits << 1// 00001000
  • shiftBits << 2// 00010000
  • shiftBits << 5// 10000000
  • shiftBits << 6// 00000000
  • shiftBits >> 2// 00000001

You can use bit shifting to encode and decode values within other data types:

  • letpink: UInt32 = 0xCC6699
  • letredComponent = (pink & 0xFF0000) >> 16// redComponent is 0xCC, or 204
  • letgreenComponent = (pink & 0x00FF00) >> 8// greenComponent is 0x66, or 102
  • letblueComponent = pink & 0x0000FF// blueComponent is 0x99, or 153

Shifting Behavior for Signed Integers

The shifting behavior is more complex for signed integers than for unsigned integers, because of the way signed integers are represented in binary. (The examples below are based on 8-bit signed integers for simplicity, but the same principles apply for signed integers of any size.)

Signed integers use their first bit (known as the sign bit) to indicate whether the integer is positive or negative. A sign bit of 0 means positive, and a sign bit of 1 means negative.

The remaining bits (known as the value bits) store the actual value. Positive numbers are stored in exactly the same way as for unsigned integers, counting upwards from 0.

Overflow Operators

  • varpotentialOverflow = Int16.max
  • // potentialOverflow equals 32767, which is the largest value an Int16 can hold
  • potentialOverflow += 1
  • // this causes an error

Providing error handling when values get too large or too small gives you much more flexibility when coding for boundary value conditions.

However, when you specifically want an overflow condition to truncate the number of available bits, you can opt in to this behavior rather than triggering an error. Swift provides five arithmetic overflow operators that opt in to the overflow behavior for integer calculations. These operators all begin with an ampersand (&):

  • Overflow addition (&+)
  • Overflow subtraction (&-)
  • Overflow multiplication (&*)
  • Overflow division (&/)
  • Overflow remainder (&%)
  • varwillOverflow = UInt8.max
  • // willOverflow equals 255, which is the largest value a UInt8 can hold
  • willOverflow = willOverflow &+ 1
  • // willOverflow is now equal to 0

Value Overflow

 

Value Underflow

  • varwillUnderflow = UInt8.min
  • // willUnderflow equals 0, which is the smallest value a UInt8 can hold
  • willUnderflow = willUnderflow &- 1
  • // willUnderflow is now equal to 255
  • varsignedUnderflow = Int8.min
  • // signedUnderflow equals -128, which is the smallest value an Int8 can hold
  • signedUnderflow = signedUnderflow &- 1
  • // signedUnderflow is now equal to 127
  • letx = 1
  • lety = x / 0

Division by Zero

 

  • letx = 1
  • lety = x &/ 0
  • // y is equal to 0

Precedence and Associativity

Operator precedence gives some operators higher priority than others; these operators are applied first.

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.”

Operator Functions

Classes and structures can provide their own implementations of existing operators. This is known asoverloading the existing operators.

The example below shows how to implement the arithmetic addition operator (+) for a custom structure. The arithmetic addition operator is a binary operator because it operates on two targets and is said to be infixbecause it appears in between those two targets.

  • structVector2D {
  • varx = 0, y = 0.0
  • }
  • func + (left: Vector2D, right: Vector2D) -> Vector2D {
  • returnVector2D(x: left.x + right.x, y: left.y + right.y)
  • }

 

  • letvector = Vector2D(x: 0, y: 1.0)
  • letanotherVector = Vector2D(x: 0, y: 4.0)
  • letcombinedVector = vector + anotherVector
  • // combinedVector is a Vector2D instance with values of (5.0, 5.0)

Prefix and Postfix Operators

The example shown above demonstrates a custom implementation of a binary infix operator. Classes and structures can also provide implementations of the standard unary operators. Unary operators operate on a single target. They are prefix if they precede their target (such as -a) and postfix operators if they follow their target (such as i++).

  • prefixfunc – (vector: Vector2D) -> Vector2D {
  • returnVector2D(x: -vector.x, y: -vector.y)
  • }

 

  • letpositive = Vector2D(x: 0, y: 4.0)
  • letnegative = -positive
  • // negative is a Vector2D instance with values of (-3.0, -4.0)
  • letalsoPositive = -negative
  • // alsoPositive is a Vector2D instance with values of (3.0, 4.0)

Compound Assignment Operators

Compound assignment operators combine assignment (=) with another operation. For example, the addition assignment operator (+=) combines addition and assignment into a single operation. You mark a compound assignment operator’s left input parameter as inout, because the parameter’s value will be modified directly from within the operator function.

The example below implements an addition assignment operator function for Vector2D instances:

  • func += (inoutleft: Vector2D, right: Vector2D) {
  • left = left + right
  • }

 

  • varoriginal = Vector2D(x: 0, y: 2.0)
  • letvectorToAdd = Vector2D(x: 0, y: 4.0)
  • original += vectorToAdd
  • // original now has values of (4.0, 6.0)

 

  • prefixfunc ++ (inoutvector: Vector2D) -> Vector2D {
  • vector += Vector2D(x: 0, y: 1.0)
  • returnvector
  • }

 

  • vartoIncrement = Vector2D(x: 0, y: 4.0)
  • letafterIncrement = ++toIncrement
  • // toIncrement now has values of (4.0, 5.0)
  • // afterIncrement also has values of (4.0, 5.0)

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 (!=). It is not possible for Swift to guess what would qualify as “equal” for your own custom types, because the meaning of “equal” depends on the roles that those types play in your code.

  • func == (left: Vector2D, right: Vector2D) -> Bool {
  • return (left.x == right.x) && (left.y == right.y)
  • }
  • func != (left: Vector2D, right: Vector2D) -> Bool {
  • return !(left == right)
  • }

 

  • lettwoThree = Vector2D(x: 0, y: 3.0)
  • letanotherTwoThree = Vector2D(x: 0, y: 3.0)
  • iftwoThree == anotherTwoThree {
  • println(“These two vectors are equivalent.”)
  • }
  • // prints “These two vectors are equivalent.”

Custom Operators

You can declare and implement your own custom operators in addition to the standard operators provided by Swift.

Custom operators can start with the characters / = – + * % < > ! & | ^ . ~, or Unicode math, symbol, arrow, dingbat, and line/box drawing characters. Their second and subsequent characters can be any of the above characters, and/or Unicode combining characters.

 

New operators are declared at a global level using the operator keyword, and are marked with the prefix,infix or postfix modifiers:

  • prefixoperator +++ {}

 

  • prefixfunc +++ (inoutvector: Vector2D) -> Vector2D {
  • vector += vector
  • returnvector
  • }

 

  • vartoBeDoubled = Vector2D(x: 0, y: 4.0)
  • letafterDoubling = +++toBeDoubled
  • // toBeDoubled now has values of (2.0, 8.0)
  • // afterDoubling also has values of (2.0, 8.0)

Precedence and Associativity for Custom Infix Operators

Custom infix operators can also specify a precedence and an associativity.

 

The possible values for associativity are left, right, and none. Left-associative operators associate to the left if written next to other left-associative operators of the same precedence. Similarly, right-associative operators associate to the right if written next to other right-associative operators of the same precedence. Non-associative operators cannot be written next to other operators with the same precedence.

 

  • infixoperator +- { associativityleftprecedence140 }
  • func +- (left: Vector2D, right: Vector2D) -> Vector2D {
  • returnVector2D(x: left.x + right.x, y: left.y – right.y)
  • }
  • letfirstVector = Vector2D(x: 0, y: 2.0)
  • letsecondVector = Vector2D(x: 0, y: 4.0)
  • letplusMinusVector = firstVector +- secondVector
  • // plusMinusVector is a Vector2D instance with values of (4.0, -2.0)

 

Broken SharePoint Application

Sometimes I have encountered problems with SharePoint sites so that they do not work. One of the quick solutions I have found is to simply create a new web application. Remove the content database from you actual application and connect it to your new application.

This is not something you want to do in a production or test environment BUT if you are in a hurry and you are wondering why your web application is not working and after all check everything seems OK(also check your DNS settings). Then you could consider this option in your development environments.

Apple and the new programming language Swift

Hi,

As a developer myself I am exited about this news. Apple just announced yesterday a new programming language named Swift which to my understanding in the long run will replace Objective-C. For me this is great news because Objective-C is kind of a hurdle to learn mostly because I’ve done so much development on C/C++, Java and C# languages that the syntax in Objective-C was a bit strange to me. I did some small apps a while ago but never really felt like this was easy. Anyway my preferences are my own thing :).

What is great about the new Swift language is that it is very VERY similar to C# or Java also. Taking a quick glance at the language guide and the syntax and functionality are very similar to those of C# and Java. Although Apple has chosen to use some rather strange notations and syntax naming in some part BUT compared to Objective-C it is great. I know this will lower my bar to making some new apps for the iOS environment.

For me as a developer this is a great news for two reasons:

1. I do not have to spent that much time learning Objective-C and avoiding mistakes that someone who already knows it knows to avoid.

2. And as the second reason it is time and cost effectiveness. IF I want to make an app for iOS now I can do it faster (based on what Apple says and what I’ve noticed). Also I do not have to buy third party tools like Xamarian to do the development faster in a language that is more familiar to me. Ofcourse using Xamarian you could theoretically deploy your application on multiple platforms BUT the license fees are rather big if you are a one man team or a small company with little or no real funds.

Anyways greats news from a developers perspective. Here are a couple of links to Swift:
Swift Language Guide

Apple Swift Developer Page

Well Time will tell what is Apple planning and how it will affect developers who are interested in Apple’s ecosystem.

SharePoint problems fixed – Code tricks – Part 1

Hi,

Wanted to post some code tricks regarding SharePoint. Tricks which I have had to do more than once and tricks that are not so common but hard and useful:

Retrieve available web templates from a web:

SPWebTemplateCollection wtc = topNewsSite.GetAvailableWebTemplates(1035);

Set web default page layout(when you create new pages):

PublishingSite pubSite = newPublishingSite(yourSiteCollection);

                        {

                            PublishingWeb pubWeb = PublishingWeb.IsPublishingWeb(yourPublishingWeb) ? PublishingWeb.GetPublishingWeb(yourPublishingWeb) : null;

                            if(pubWeb != null)

                            {

                                PageLayout pageLayout = pubSite.PageLayouts.FirstOrDefault( item => item.Name == “yourpagelayout.aspx”);

                                if(pageLayout != null)

                                {

                                    pubWeb.SetDefaultPageLayout(pageLayout, false);

                                    pubWeb.Update();

                                }

                            }

                        }

 

Copy(Add), Modify a webpart from one page to another with changes to webpart display template

// temp variable for a MS webpart which we will copy from one page to another page

                    Microsoft.Office.Server.Search.WebControls.ContentBySearchWebPart newsWP = null;

                    // Get the needed page from your site and get that pages web part manager

                    using (var wpm = topNewsSite.Lists["Pages"].Items[0].File.GetLimitedWebPartManager(PersonalizationScope.Shared))

                    {

                        // Search for the right webpart(you could use LINQ instead of a foreach)

                        foreach (var wp in wpm.WebParts)

                        {

                            // Check the type of the webpart

                            if ((wp is Microsoft.Office.Server.Search.WebControls.ContentBySearchWebPart))

                            {

                                // Make sure it is a ContentBySearchWebPart

                                newsWP = wp as Microsoft.Office.Server.Search.WebControls.ContentBySearchWebPart;

                               

                                // Check that we have the right webpart

                                if (newsWP != null && newsWP.Title.Contains(“My News Webpart”))

                                {

                                    // Get the page you need where you want the web part to be copied

                                    SPListItem page = newWeb.Lists["Pages"].Items[0];

                                    SPFile file = page.File;

                                    file.CheckOut();

                                    // Get the web part manager of the destination page where to copy the webpart

                                    using (var wpmNewsWeb = file.GetLimitedWebPartManager(PersonalizationScope.Shared))

                                    {

                                        // Change the web part display template for a listing with paging

                                        newsWP.RenderTemplateId = “~sitecollection/_catalogs/masterpage/Display Templates/Content Web Parts/Control_ListWithPaging.js”;

                                        // Add the web part to the page

                                        wpmNewsWeb.AddWebPart(newsWP, “CenterZone”, 0);

                                        // Make sure to call this to save the changes to the webpart

                                        wpmNewsWeb.SaveChanges(newsWP);

                                    }

                                    page.Update();

                                    file.CheckIn(“”);

                                    file.Publish(“”);

                                    file.Approve(“”);

                                }

                            }

                        }

                    }

 

Good to Know: Windows Server 2012 – Part 4

Hi this is my part four of resources for Windows Server 2012(and older ones also):

Add-DnsServerDirectoryPartition http://technet.microsoft.com/en-us/library/jj649942(v=wps.620).aspx
Add-DnsServerPrimaryZone http://technet.microsoft.com/en-us/library/jj649876(v=wps.620).aspx
Adding a Reverse Lookup Zone http://technet.microsoft.com/en-us/library/cc961414.aspx
Add-PswaAuthorizationRule http://technet.microsoft.com/en-us/library/jj592890(v=wps.620).aspx
Add-VMRemoteFx3dVideoAdapter http://technet.microsoft.com/en-us/library/hh848520(v=wps.620).aspx
Authorize a DHCP server in Active Directory http://technet.microsoft.com/en-us/library/cc759688(v=ws.10).aspx
Block Inheritance http://technet.microsoft.com/en-us/library/cc731076.aspx
Configure a Server Core Server with Sconfig.cmd http://technet.microsoft.com/en-us/library/jj647766.aspx
Configure Memory and Processors http://technet.microsoft.com/en-us/library/cc742470.aspx
Delegate Control of an Organizational Unit http://technet.microsoft.com/en-us/library/cc732524.aspx
Deploy Clustered Storage Spaces http://technet.microsoft.com/en-us/library/jj822937.aspx 
Deploying a GlobalNames Zone http://technet.microsoft.com/en-us/library/cc731744.aspx
Deploying Microsoft RemoteFX on a Single Remote Desktop Virtualization Host Server Step-by-Step Guide http://technet.microsoft.com/en-us/library/ff817586(v=ws.10).aspx
Deploying Network Load Balancing (NLB) and Virtual Machines on Windows Server 2008 R2 http://blogs.msdn.com/b/clustering/archive/2010/07/01/10033544.aspx
Deployment Image Servicing and Management Command-Line Options http://technet.microsoft.com/en-us/library/dd744382(v=ws.10).aspx
Dsadd http://technet.microsoft.com/en-us/library/cc753708(v=ws.10).aspx
Enable-VMRemoteFXPhysicalVideoAdapter http://technet.microsoft.com/en-us/library/hh848506(v=wps.620).aspx
Enforce a Group Policy Object Link http://technet.microsoft.com/en-us/library/cc753909.aspx
Evaluation Versions and Upgrade Options for Windows Server 2012 http://technet.microsoft.com/en-us/library/jj574204.aspx
Evaluation Versions and Upgrade Options for Windows Server 2012 http://technet.microsoft.com/en-us/library/jj574204.aspx
Get-DnsServerDiagnostics http://technet.microsoft.com/en-us/library/jj649883(v=wps.620).aspx
Grant a Member the Right to Logon Locally http://technet.microsoft.com/en-us/library/ee957044(v=ws.10).aspx
How to remove data in Active Directory after an unsuccessful domain controller demotion http://support.microsoft.com/kb/216498
How User Account Control Works http://technet.microsoft.com/en-us/library/jj574202.aspx
Hyper-V Dynamic Memory Configuration Guide http://technet.microsoft.com/en-us/library/ff817651(v=ws.10).aspx
Hyper-V Virtual Switch Explained, Part 2 http://www.altaro.com/hyper-v/hyper-v-virtual-switch-explained-part-2/ 
Hyper-V Virtual Switch Overview http://technet.microsoft.com/en-us/library/hh831823.aspx
ImageX Command-Line Options http://technet.microsoft.com/en-us/library/cc749447(v=ws.10).aspx
Install-PswaWebApplication http://technet.microsoft.com/en-us/library/jj592894(v=wps.620).aspx
Install-RemoteAccess http://technet.microsoft.com/en-us/library/hh918408(v=wps.620).aspx
Internet Protocol Version 6 Address Space http://www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xml
Link a Group Policy Object http://technet.microsoft.com/en-us/library/cc732979.aspx
Loopback processing with merge or replace http://technet.microsoft.com/en-us/library/cc782810(v=ws.10).aspx
Manage Multiple, Remote Servers with Server Manager http://technet.microsoft.com/en-us/library/hh831456.aspx
Managing a Server Core installation: Overview http://technet.microsoft.com/en-us/library/ee441255(v=ws.10).aspx
Migrate Print and Document Services to Windows Server 2012 http://technet.microsoft.com/en-us/library/jj134150.aspx
Operations master roles http://technet.microsoft.com/en-us/library/cc773108(v=ws.10).aspx
Print and Document Services Overview http://technet.microsoft.com/en-us/library/hh831468.aspx
Remote Desktop Gateway Manager http://technet.microsoft.com/en-us/library/cc725706.aspx
Remove-ADComputer http://technet.microsoft.com/en-us/library/ee617250.aspx
Remove-WindowsFeature http://technet.microsoft.com/en-us/library/ee662310.aspx
Sc config http://technet.microsoft.com/en-us/library/cc990290(v=ws.10).aspx
Security Tools to Administer Windows Server 2012 http://technet.microsoft.com/en-us/library/jj730960.aspx
Set up recovery actions to take place when a service fails http://technet.microsoft.com/en-us/library/cc738230(v=ws.10).aspx
Set-BCAuthentication http://technet.microsoft.com/en-us/library/hh848404(v=wps.620).aspx
Set-DnsServer http://technet.microsoft.com/en-us/library/jj649845(v=wps.620).aspx
Set-DnsServerDsSetting http://technet.microsoft.com/en-us/library/jj649874.aspx
Set-DnsServerForwarder http://technet.microsoft.com/en-us/library/jj649887(v=wps.620).aspx
Set-DnsServerSetting http://technet.microsoft.com/en-us/library/jj649909.aspx
Set-GPPermissions http://technet.microsoft.com/en-us/library/ee461038.aspx
Set-WSManInstance http://technet.microsoft.com/en-us/library/hh849875.aspx
Set-WSManQuickConfig http://technet.microsoft.com/en-us/library/hh849867.aspx
Storage Pools… Dive right in! http://blogs.technet.com/b/canitpro/archive/2012/12/13/storage-pools-dive-right-in.aspx
Switching Between the GUI and Server Core in Windows Server 2012 http://www.petri.co.il/switching-gui-server-core-windows-server-2012.htm
Troubleshooting Windows Firewall with Advanced Security in Windows Server 2012 http://social.technet.microsoft.com/wiki/contents/articles/13894.troubleshooting-windows-firewall-with-advanced-security-in-windows-server-2012.aspx
Updating root hints http://technet.microsoft.com/en-us/library/cc758353(v=ws.10).aspx
Using System Configuration (msconfig) http://windows.microsoft.com/en-us/windows-vista/using-system-configuration
Using the Set-Service Cmdlet http://technet.microsoft.com/en-us/library/ee176963.aspx
Verifying Your Basic DNS Configuration http://technet.microsoft.com/en-us/library/cc959303.aspx
What’s New in Hyper-V for Windows Server 2012 http://technet.microsoft.com/en-us/library/hh831410.aspx
What’s New in Hyper-V for Windows Server 2012 http://technet.microsoft.com/en-us/library/hh831410.aspx
Windows and GPT FAQ http://msdn.microsoft.com/en-us/library/windows/hardware/gg463525.aspx