[Swift]A Review of "A Swift Tour"

作者 Shilei Tian 日期 2016-09-18
[Swift]A Review of "A Swift Tour"
  1. The value of a constant doesn’t need to be known at compile time, but you must assign it a value exactly once.
  2. Values are never implicitly converted to another type. If you need to convert a value to a different type, explicitly make an instance of the desired type.
  3. Write the value in parentheses, and write a backslash (\) before the parentheses.
  4. In an if statement, the conditional must be a Boolean expression — this means that code such as if score { ... } is an error, not an implicit comparison to zero.
  5. An optional value either contains a value or contains nil to indicate that a value is missing. Write a question mark (?) after the type of a value to mark the value as optional.
  6. You can use if and let together to work with values that might be missing.
  7. Another way to handle optional values is to provide a default value using the ?? operator. If the optional value is missing, the default value is used instead.
  8. Execution doesn’t continue to the next case, so there is no need to explicitly break out of the switch at the end of each case’s code.
  9. You can keep an index in a loop by using ..< to make a range of indexes. Use ..< to make a range that omits its upper value, and use ... to make a range that includes both values.
  10. Write a custom argument label before the parameter name, or write _ to use no argument label.
  11. Use a tuple to make a compound value — for example, to return multiple values from a function. The elements of a tuple can be referred to either by name or by number. For example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0]
    var max = scores[0]
    var sum = 0

    for score in scores {
    if score > max {
    max = score
    } else if score < min {
    min = score
    }
    sum += score
    }

    return (min, max, sum)
    }
    let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
    print(statistics.2) // Here!
  12. Functions can also take a variable number of arguments, collecting them into an array. For example:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    func sumOf(numbers: Int...) -> Int {
    var sum = 0
    for number in numbers {
    sum += number
    }
    return sum
    }
    sumOf()
    sumOf(numbers: 42, 597, 12) // Notice here, the parameters
  13. Functions are a first-class type. This means that a function can return another function as its value. And a function can take another function as one of its arguments.

  14. You can write a closure without a name by surrounding code with braces ({}). Use in to separate the arguments and return type from the body.
  15. When a closure’s type is already known, such as the callback for a delegate, you can omit the type of its parameters, its return type, or both.
  16. You can refer to parameters by number instead of by name—this approach is especially useful in very short closures. A closure passed as the last argument to a function can appear immediately after the parentheses. When a closure is the only argument to a function, you can omit the parentheses entirely. For example:

    1
    2
    var numbers = [20, 19, 7, 12]
    print(numbers.sorted {$0 > $1})
  17. Every property needs a value assigned—either in its declaration or in the initializer.

  18. Use deinit to create a deinitializer if you need to perform some cleanup before the object is deallocated.
  19. There is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.
  20. Methods on a subclass that override the superclass’s implementation are marked with override — overriding a method by accident, without override, is detected by the compiler as an error.
  21. In addition to simple properties that are stored, properties can have a getter and a setter.
  22. In the setter, the new value has the implicit name newValue. You can provide an explicit name in parentheses after set.
  23. The initializer for the class has three different steps:
    1. Setting the value of properties that the subclass declares.
    2. Calling the superclass’s initializer.
    3. Changing the value of properties defined by the superclass. Any additional setup work that uses methods, getters, or setters can also be done at this point.
  24. If you don’t need to compute the property but still need to provide code that is run before and after setting a new value, use willSet and didSet.
  25. When working with optional values, you can write ? before operations like methods, properties, and subscripting. If the value before the ? is nil, everything after the ? is ignored and the value of the whole expression is nil. Otherwise, the optional value is unwrapped, and everything after the ? acts on the unwrapped value. In both cases, the value of the whole expression is an optional value.
  26. Use enum to create an enumeration. Like classes and all other named types, enumerations can have methods associated with them. By default, Swift assigns the raw values starting at zero and incrementing by one each time, but you can change this behavior by explicitly specifying values.
  27. One of the most important differences between structures and classes is that structures are always copied when they are passed around in your code, but classes are passed by reference.
  28. Associated values and raw values are different: The raw value of an enumeration case is the same for all of its instances, and you provide the raw value when you define the enumeration.
  29. Classes, enumerations, and structs can all adopt protocols. Notice the use of the mutating keyword in the declaration to mark a method that modifies the structure.
  30. Use extension to add functionality to an existing type, such as new methods and computed properties. You can use an extension to add protocol conformance to a type that is declared elsewhere, or even to a type that you imported from a library or framework.
  31. When you work with values whose type is a protocol type, methods outside the protocol definition are not available.
  32. Another way to handle errors is to use try? to convert the result to an optional. If the function throws an error, the specific error is discarded and the result is nil. Otherwise, the result is an optional containing the value that the function returned.
  33. Use defer to write a block of code that is executed after all other code in the function, just before the function returns. The code is executed regardless of whether the function throws an error. You can use defer to write setup and cleanup code next to each other, even though they need to be executed at different times.
  34. Use where right before the body to specify a list of requirements.