Types

Type Inference

  • Equivalent:

    let hello = 'hi mom'
    let hello: String = 'hi mom'
    

Value Type

  • It's a type whose value is copied  when it’s assigned to a variable or constant, or when it’s passed to a function.

  • Value Types :

    • Integers

    • Floating-point numbers

    • Booleans

    • Strings

    • Arrays

    • Dictionaries

    • Structs

      • All basic types are implemented as structures behind the scenes.

    • Enums

  • Ex1 :

    struct Resolution {
        var width = 0
        var height = 0
    }
    
    let hd = Resolution(width: 1920, height: 1080)
    var cinema = hd
    
    • Because Resolution  is a structure, a copy  of the existing instance is made, and this new copy is assigned to cinema . Even though hd  and cinema  now have the same width and height, they’re two completely different instances behind the scenes.

Reference Types

  • Reference types  are not  copied when they’re assigned to a variable or constant, or when they’re passed to a function. Rather than a copy, a reference to the same existing instance is used.

  • Reference Types :

    • Classes

  • Ex1 :

let tenEighty = VideoMode()
tenEighty.resolution = hd
tenEighty.interlaced = true
tenEighty.name = "1080i"
tenEighty.frameRate = 25.0

let alsoTenEighty = tenEighty
alsoTenEighty.frameRate = 30.0

print("The frameRate property of tenEighty is now \(tenEighty.frameRate)")
// Prints "The frameRate property of tenEighty is now 30.0". Both are 30.0.

Booleans

let orangesAreOrange = true
let turnipsAreDelicious = false
  • Not allowed :

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

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

Numbers

Int
  • Types :

    • Int8

    • Int16

    • Int32

    • Int64

    • UInt8

    • UInt16

    • UInt32

    • UInt64

  • Generic :

    • In most cases, you don’t need to pick a specific size of integer to use in your code. Swift provides an additional integer type, Int  / UInt , which has the same size as the current platform’s native word size:

      • On a 32-bit platform:

        • Int  / UInt  is the same size as Int32  / UInt32 .

      • On a 64-bit platform:

        • Int  / UInt  is the same size as Int64  / UInt64 .

    • Unless you need to work with a specific size of integer, always use Int  for integer values in your code. This aids code consistency and interoperability.

    • Even on 32-bit platforms, Int  can store any value between -2,147,483,648  and 2,147,483,647 , and is large enough for many integer ranges.

    • Note about UInt :

      • Use UInt  only when you specifically need an unsigned integer type with the same size as the platform’s native word size. If this isn’t the case, Int  is preferred, even when the values to be stored are known to be nonnegative. A consistent use of Int  for integer values aids code interoperability, avoids the need to convert between different number types, and matches integer type inference, as described in Type Safety and Type Inference .

  • Bounds :

    • UInt8.min

    • UInt8.max

Float
  • Represents a 32-bit floating-point number.

  • Can have a precision as little as 6 decimal digits.

Double
  • Represents a 64-bit floating-point number.

  • Has a precision of at least 15 decimal digits.

  • In situations where either type would be appropriate, Double  is preferred.

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

    • 1.25e2  means 1.25 x 10², or 125.0 .

    • 1.25e-2  means 1.25 x 10⁻², or 0.0125 .

  • Hexadecimals:

    • 0xFp2  means 15 x 2², or 60.0 .

    • 0xFp-2  means 15 x 2⁻², or 3.75 .

Formatting
let paddedDouble = 000123.456
let oneMillion = 1_000_000
let justOverOneMillion = 1_000_000.000_000_1

String

Literals
  • Singleline :

    let someString = "Some string literal value"
    
  • Multiline :

    let quotation = """
    The White Rabbit put on his spectacles.  "Where shall I begin,
    please your Majesty?" he asked.
    
    "Begin at the beginning," the King said gravely, "and go on
    till you come to the end; then stop."
    """
    
    let singleLineString = "These are the same."
    let multilineString = """
    These are the same.
    """
    
    let softWrappedQuotation = """
    The White Rabbit put on his spectacles.  "Where shall I begin, \
    please your Majesty?" he asked.
    
    "Begin at the beginning," the King said gravely, "and go on \
    till you come to the end; then stop."
    """
    
    • If you’re using multiline string literals to build up the lines of a longer string, you want every line in the string to end with a line break, including the last line.

      let badStart = """
          one
          two
          """
      let end = """
          three
          """
      print(badStart + end)
      // Prints two lines:
      // one
      // twothree
      
      
      let goodStart = """
          one
          two
      
          """
      print(goodStart + end)
      // Prints three lines:
      // one
      // two
      // three
      
Concatenation
"hello, " + "world"  // equals "hello, world"
Interpolation
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"
// message is "3 times 2.5 is 7.5"
Chars
for character in "Dog!🐶" {
    print(character)
}
let exclamationMark: Character = "!"
let catCharacters: [Character] = ["C", "a", "t", "!", "🐱"]
let catString = String(catCharacters)
print(catString)
// Prints "Cat!🐱"
Special Chars
  • \0  (null character)

  • \\  (backslash)

  • \t  (horizontal tab)

  • \n  (line feed)

  • \r  (carriage return)

  • \"  (double quotation mark)

  • \'  (single quotation mark)

  • \u{ n } , where n  is a 1–8 digit hexadecimal number.

  • How to avoid using special chars :

    print(#"Write an interpolated string in Swift using \(multiplier)."#)
    // Prints "Write an interpolated string in Swift using \(multiplier)."
    
    let threeMoreDoubleQuotationMarks = #"""
    Here are three more double quotes: """
    "\""#  // remove the backslash
    
Manipulation
  • Length:

    let unusualMenagerie = "Koala 🐨, Snail 🐌, Penguin 🐧, Dromedary 🐪"
    print("unusualMenagerie has \(unusualMenagerie.count) characters")
    // Prints "unusualMenagerie has 40 characters"
    
  • Insert and Remove:

    var welcome = "hello"
    welcome.insert("!", at: welcome.endIndex)
    // welcome now equals "hello!"
    
    
    welcome.insert(contentsOf: " there", at: welcome.index(before: welcome.endIndex))
    // welcome now equals "hello there!"
    
  • Subranges:

    welcome.remove(at: welcome.index(before: welcome.endIndex))
    // welcome now equals "hello there"
    
    let range = welcome.index(welcome.endIndex, offsetBy: -6)..<welcome.endIndex
    welcome.removeSubrange(range)
    // welcome now equals "hello"
    
  • Substrings:

    let greeting = "Hello, world!"
    let index = greeting.firstIndex(of: ",") ?? greeting.endIndex
    let beginning = greeting[..<index]
    // beginning is "Hello"
    
    
    // Convert the result to a String for long-term storage.
    let newString = String(beginning)
    
  • Prefixes:

    let romeoAndJuliet = [
        "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",
    ]
    
    // PREFIX
    var act1SceneCount = 0
    for scene in romeoAndJuliet {
        if scene.hasPrefix("Act 1 ") {
            act1SceneCount += 1
        }
    }
    print("There are \(act1SceneCount) scenes in Act 1")
    // Prints "There are 5 scenes in Act 1"
    
    
    // SUFFIX
    var mansionCount = 0
    var cellCount = 0
    for scene in romeoAndJuliet {
        if scene.hasSuffix("Capulet's mansion") {
            mansionCount += 1
        } else if scene.hasSuffix("Friar Lawrence's cell") {
            cellCount += 1
        }
    }
    print("\(mansionCount) mansion scenes; \(cellCount) cell scenes")
    // Prints "6 mansion scenes; 2 cell scenes"
    

Tuples

Creation
  • Tuples  group multiple values into a single compound value.

  • The values within a tuple can be of any type and don’t have to be of the same type as each other.

    let http404Error = (404, "Not Found")
    // http404Error is of type (Int, String), and equals (404, "Not Found")
    
  • If you name the elements in a tuple, you can use the element names to access the values of those elements:

    let http200Status = (statusCode: 200, description: "OK")
    
  • Tuples are particularly useful as the return values of functions. A function that tries to retrieve a web page might return the (Int, String)  tuple type to describe the success or failure of the page retrieval. By returning a tuple with two distinct values, each of a different type, the function provides more useful information about its outcome than if it could only return a single value of a single type.

Access
  • Index :

    print("The status code is \(http404Error.0)")
    // Prints "The status code is 404"
    print("The status message is \(http404Error.1)")
    // Prints "The status message is Not Found"
    
  • Name  (if defined):

    print("The status code is \(http200Status.statusCode)")
    // Prints "The status code is 200"
    print("The status message is \(http200Status.description)")
    // Prints "The status message is OK"
    
  • Destructuring / Decomposition :

    let (statusCode, statusMessage) = http404Error
    print("The status code is \(statusCode)")
    // Prints "The status code is 404"
    print("The status message is \(statusMessage)")
    // Prints "The status message is Not Found"
    
    • If you only need some of the tuple’s values, ignore parts of the tuple with an underscore ( _ ) when you decompose the tuple:

      let (justTheStatusCode, _) = http404Error
      print("The status code is \(justTheStatusCode)")
      // Prints "The status code is 404"
      
Logical Comparisons in Tuples
  • You can compare two tuples if they have the same type and the same number of values. Tuples are compared from left to right, one value at a time, until the comparison finds two values that aren’t equal.

(1, "zebra") < (2, "apple")   // true because 1 is less than 2; "zebra" and "apple" aren't compared
(3, "apple") < (3, "bird")    // true because 3 is equal to 3, and "apple" is less than "bird"
(4, "dog") == (4, "dog")      // true because 4 is equal to 4, and "dog" is equal to "dog"

Arrays

Creation
var someInts: [Int] = []
print("someInts is of type [Int] with \(someInts.count) items.")
// Prints "someInts is of type [Int] with 0 items."
var threeDoubles = Array(repeating: 0.0, count: 3)
// threeDoubles is of type [Double], and equals [0.0, 0.0, 0.0]
var sixDoubles = threeDoubles + anotherThreeDoubles
  • New array of Strings, via the content of a Dictionary:

    let airportCodes = [String](airports.keys)
    // airportCodes is ["LHR", "YYZ"]
    
    
    let airportNames = [String](airports.values)
    // airportNames is ["London Heathrow", "Toronto Pearson"]
    
Access
var firstItem = shoppingList[0]
// firstItem is equal to "Eggs"
Modification
  • You can use subscript syntax to change an existing  value at a given index:

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
Insert
  • Via append :

    shoppingList.append("Flour")
    // shoppingList now contains 3 items, and someone is making pancakes
    
  • Via insert :

    shoppingList.insert("Maple Syrup", at: 0)
    // shoppingList now contains 7 items
    // "Maple Syrup" is now the first item in the list
    
  • Via += :

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

    let mapleSyrup = shoppingList.remove(at: 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
    
  • removeLast .

Other common methods
  • isEmpty

Set

  • A set  stores distinct values of the same type in a collection with no defined ordering.

  • Uses :

    • You can use a set instead of an array when the order of items isn’t important

    • Or when you need to ensure that an item only appears once .

  • My interpretation :

    • It's a "dictionary that only has keys, no values" .

Creation
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
// Prints "letters is of type Set<Character> with 0 items."
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]
// favoriteGenres has been initialized with three initial items
var favoriteGenres: Set = ["Rock", "Classical", "Hip hop"]
Modification
letters.insert("a")
// letters now contains 1 value of type Character
letters = []
// letters is now an empty set, but is still of type Set<Character>
Operations
  • Use the intersection(_:)  method to create a new set with only the values common to both sets.

  • Use the symmetricDifference(_:)  method to create a new set with values in either set, but not both.

  • Use the union(_:)  method to create a new set with all of the values in both sets.

  • Use the subtracting(_:)  method to create a new set with values not in the specified set.

Logic
  • Contains :

if favoriteGenres.contains("Funk") {
    print("I get up on the good foot.")
} else {
    print("It's too funky in here.")
}
// Prints "It's too funky in here."
  • Use the “is equal” operator ( == ) to determine whether two sets contain all of the same values.

  • Use the isSubset(of:)  method to determine whether all of the values of a set are contained in the specified set.

  • Use the isSuperset(of:)  method to determine whether a set contains all of the values in a specified set.

  • Use the isStrictSubset(of:)  or isStrictSuperset(of:)  methods to determine whether a set is a subset or superset, but not equal to, a specified set.

  • Use the isDisjoint(with:)  method to determine whether two sets have no values in common.

Dictionary

Creation
var namesOfIntegers: [Int: String] = [:]
// namesOfIntegers is an empty [Int: String] dictionary
namesOfIntegers[16] = "sixteen"
// namesOfIntegers now contains 1 key-value pair
namesOfIntegers = [:]
// namesOfIntegers is once again an empty dictionary of type [Int: String]
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
var airports = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]
Modification
  • Insert / Modify :

    airports["LHR"] = "London"
    // the airports dictionary now contains 3 items
    
  • Remove :

    airports["APL"] = nil
    // APL has now been removed from the dictionary
    
  • updateValue

    • Returns the old  value after performing an update.

    if let oldValue = airports.updateValue("Dublin Airport", forKey: "DUB") {
        print("The old value for DUB was \(oldValue).")
    }
    // Prints "The old value for DUB was Dublin."
    
  • removeValue

    • Removes the key-value pair if it exists and returns the removed value, or returns nil  if no value existed

    if let removedValue = airports.removeValue(forKey: "DUB") {
        print("The removed airport's name is \(removedValue).")
    } else {
        print("The airports dictionary doesn't contain a value for DUB.")
    }
    // Prints "The removed airport's name is Dublin Airport."
    

Optionals

  • An optional represents two possibilities: Either there is  a value of a specified type, and you can unwrap the optional to access that value, or there isn’t  a value at all.

Creation
  • To write an optional type, you write a question mark ( ? ) after the name of the type that the optional contains.

    • For example, the type of an optional Int  is Int? .

let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)
// As the conversion `Int()` can't always be made, the returned type for convertedNumber is "optional Int".

Nil

var serverResponseCode: Int? = 404
// serverResponseCode contains an actual Int value of 404
serverResponseCode = nil
// serverResponseCode now contains no value
Default with ?
  • If you define an optional variable without providing a default value, the variable is automatically set to nil :

var surveyAnswer: String?
// surveyAnswer is automatically set to nil
What to do when it is nil
  • Skip the code that operates on the value when it’s nil .

  • ? Propagate the nil  value, by returning nil  or using the ?.  operator described in Optional Chaining .

  • Provide a fallback value, using the ??  operator.

  • Stop program execution, using the !  operator.