The Swift Programming Languageの気になった所まとめ

  • 15
  • 8

今年は、会社で半年ほどかけて The Swift Programming Language の読書会を開催していました。
わすれないうちに、Slackの内容をここにまとめておきます。(Language Guideのみ)

Strings and Characters

String and Character Equality

Extended grapheme clusters are canonically equivalent if they have the same linguistic meaning and appearance, even if they are composed from different Unicode scalars behind the scenes.

書記素クラスタは異なるUnicode scalarsで構成されていても同じ言語上の意味と外観を持つなら等価とするんですね。

Comparing Strings

Conversely, LATIN CAPITAL LETTER A (U+0041, or "A"), as used in English, is not equivalent to CYRILLIC CAPITAL LETTER A (U+0410, or "А"), as used in Russian. The characters are visually similar, but do not have the same linguistic meaning:

    let latinCapitalLetterA: Character = "\u{41}"

    let cyrillicCapitalLetterA: Character = "\u{0410}"

    if latinCapitalLetterA != cyrillicCapitalLetterA {
        print("These two characters are not equivalent.")
    // Prints "These two characters are not equivalent."

"A" != "А"。よく見ると違いますね。

Unicode Representations of Strings

You can iterate over the string with a for-in statement, to access its individual Character values as Unicode extended grapheme clusters.


Collection Types

⁠⁠⁠⁠Arrays are ordered collections of values. Sets are unordered collections of unique values. Dictionaries are unordered collections of key-value associations. ⁠⁠⁠⁠


Mutability of Collections

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.


Creating an Array by Adding Two Arrays Together

You can create a new array by adding together two existing arrays with compatible types with the addition operator (+). The new array’s type is inferred from the type of the two arrays you add together:

    var anotherThreeDoubles = Array(repeating: 2.5, count: 3)
    // anotherThreeDoubles is of type [Double], and equals [2.5, 2.5, 2.5]   
    var sixDoubles = threeDoubles + anotherThreeDoubles
    // sixDoubles is inferred as [Double], and equals [0.0, 0.0, 0.0, 2.5, 2.5, 2.5]

let arr = ["a", "b", "c"] + [1 ,2 ,3]とするとtype(of: arr)Array<Any>

Accessing and Modifying an Array

If you try to access or modify a value for an index that is outside of an array’s existing bounds, you will trigger a runtime error. You can check that an index is valid before using it by comparing it to the array’s count property. Except when count is 0 (meaning the array is empty), the largest valid index in an array will always be count - 1, because arrays are indexed from zero.


Iterating Over an Array

If you need the integer index of each item as well as its value, use the enumerated() method to iterate over the array instead. For each item in the array, the enumerated() method returns a tuple composed of an integer and the item. The integers start at zero and count up by one for each item; if you enumerate over a whole array, these integers match the items’ indices. You can decompose the tuple into temporary constants or variables as part of the iteration:

    for (index, value) in shoppingList.enumerated() {
        print("Item \(index + 1): \(value)")
    // Item 1: Six eggs
    // Item 2: Milk
    // Item 3: Flour
    // Item 4: Baking Powder
    // Item 5: Bananas



A dictionary stores associations between keys of the same type and values of the same type in a collection with no defined ordering.




Dictionary Type Shorthand Syntax

A dictionary Key type must conform to the Hashable protocol, like a set’s value type.


Accessing and Modifying a Dictionary

You can also use subscript syntax to retrieve a value from the dictionary for a particular key. Because it is possible to request a key for which no value exists, a dictionary’s subscript returns an optional value of the dictionary’s value type. If the dictionary contains a value for the requested key, the subscript returns an optional value containing the existing value for that key. Otherwise, the subscript returns nil:


You can use subscript syntax to remove a key-value pair from a dictionary by assigning a value of nil for that key:

    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

nil を代入するとDictionaryから消せます。
let removedValue = airports.removeValue(forKey: "APL")とすると、消した値を取得することもできます。

Control Flow


Every switch statement must be exhaustive.


    let num = 5
    switch num {
    case Int.min..<1:
    case 1..<100:
    case 100...Int.max:

(12/6追記 @es_kumagai さんに指摘いただきました。 )
読書会時点(Xcode7.x)では、上記コードがコンパイルできていましたが、XcodeVersion 8.1 (8B62)では、以下のようなエラーになりました。
error: switch must be exhaustive, consider adding a default clause


To explicitly fall through at the end of a particular switch case, use the fallthrough keyword


The fallthrough keyword does not check the case conditions for the switch case that it causes execution to fall into. The fallthrough keyword simply causes code execution to move directly to the statements inside the next case (or default case) block, as in C’s standard switch statement behavior.

試してみました。 where も無視されますね。

let i = 2
switch i {
case 2:
case _ where i % 3 == 0:
// 2%とprintされる

Checking API Availability

You use an availability condition in an if or guard statement to conditionally execute a block of code, depending on whether the APIs you want to use are available at runtime. The compiler uses the information from the availability condition when it verifies that the APIs in that block of code are available.
if #available(platform name version, ..., *) { }

#available は、便利だけど構文が特殊すぎて覚えにくいですね。


Functions Without Return Values

    func greet(person: String) {
        print("Hello, \(person)!")
    greet(person: "Dave")
    // Prints "Hello, Dave!"

Strictly speaking, this version of the greet(person:) function does still return a value, even though no return value is defined. Functions without a defined return type return a special value of type Void. This is simply an empty tuple, which is written as ().


Optional Tuple Return Types

An optional tuple type such as (Int, Int)? is different from a tuple that contains optional types such as (Int?, Int?). With an optional tuple type, the entire tuple is optional, not just each individual value within the tuple.


var t1: (Int, Int)? = (1, 1)
t1 = nil
// t1 = (nil, 1) // error

var t2: (Int?, Int?) = (1, 1)
// t2 = nil // error
t2 = (nil, 1)

Function Argument Labels and Parameter Names

All parameters must have unique names. Although it’s possible for multiple parameters to have the same argument label, unique argument labels help make your code more readable.


func sayHello(to to1: String, to to2 : String) {
    print("Hello \(to1), and \(to2)!")
sayHello(to: "A", to: "B")

Variadic Parameters

A function may have at most one variadic parameter.


In-Out Parameters

In-out parameters cannot have default values, and variadic parameters cannot be marked as inout.


Nested Functions

Nested functions are hidden from the outside world by default, but can still be called and used by their enclosing function. An enclosing function can also return one of its nested functions to allow the nested function to be used in another scope.

面白いのですが、returnする可能性があるNested functionsの型がすべて同じでないといけないので、あまり使いみちはなさそうだと思いました。


Capturing Values

As an optimization, Swift may instead capture and store a copy of a value if that value is not mutated by a closure, and if the value is not mutated after the closure is created.
Swift also handles all memory management involved in disposing of variables when they are no longer needed.


If you assign a closure to a property of a class instance, and the closure captures that instance by referring to the instance or its members, you will create a strong reference cycle between the closure and the instance. Swift uses capture lists to break these strong reference cycles.


Escaping Closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

escapingについてに説明です。関数の引数でクロージャを受け渡すときに escaping が必要になる条件について書かれています。

スクリーンショット 2016-12-04 18.10.20.png




Enumeration Syntax

Unlike C and Objective-C, Swift enumeration cases are not assigned a default integer value when they are created.


enum Num: Int {
    case a, b, c
// 0 とprintされる
// 1 とprintされる
// 2 とprintされる
enum Str: String {
    case a, b, c
// a とprintされる
// b とprintされる
// c とprintされる

Associated Values

Swiftでよく利用されるEnumのAssociated Valuesについて、丁寧に説明されています。

Classes and Structures

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:


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.


Assignment and Copy Behavior for Strings, Arrays, and Dictionaries

In Swift, many basic data types such as String, Array, and Dictionary are implemented as structures. This means that data such as 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.


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.



Property Observers

The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They are not called while a class is setting its own properties, before the superclass initializer has been called.


If you pass a property that has observers to a function as an in-out parameter, the willSet and didSet observers are always called. This is because of the copy-in copy-out memory model for in-out parameters: The value is always written back to the property at the end of the function.

in-out のパラメータに受け渡すと、willSetdidSetが呼び出されます。

Global and Local Variables

Global constants and variables are always computed lazily, in a similar manner to Lazy Stored Properties. Unlike lazy stored properties, global constants and variables do not need to be marked with the lazy modifier.
Local constants and variables are never computed lazily.


Type Properties

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.



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.

mutating の説明です。

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:

    struct Point {
        var x = 0.0, y = 0.0
        mutating func moveBy(x deltaX: Double, y deltaY: Double) {
            self = Point(x: x + deltaX, y: y + deltaY)


Type Methods

Within the body of a type method, the implicit self property refers to the type itself, rather than an instance of that type. This means that you can use self to disambiguate between type properties and type method parameters, just as you do for instance properties and instance method parameters.



You can define multiple subscripts for a single type, and the appropriate subscript overload to use is selected based on the type of index value you pass to the subscript. Subscripts are not limited to a single dimension, and you can define subscripts with multiple input parameters to suit your custom type’s needs.



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.

Overriding Properties

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.


If you provide a setter as part of a property override, you must also provide a getter for that override. If you don’t want to modify the inherited property’s value within the overriding getter, you can simply pass through the inherited value by returning super.someProperty from the getter, where someProperty is the name of the property you are overriding.



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.


When you assign a default value to a stored property, or set its initial value within an initializer, the value of that property is set directly, without calling any property observers.

property observersのタイミング、地味にハマりそうですね。

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.


Initializer Delegation for Value Types

If you want your custom value type to be initializable with the default initializer and memberwise initializer, and also with your own custom initializers, write your custom initializers in an extension rather than as part of the value type’s original implementation.

ここまで指定してくれるなら、golangのgo fmtみたいにデフォルトでコードフォーマット提供してほしいなと思いました。

Note that if you define a custom initializer for a value type, you will no longer have access to the default initializer (or the memberwise initializer, if it is a structure) for that type. This constraint prevents a situation in which additional essential setup provided in a more complex initializer is accidentally circumvented by someone using one of the automatic initializers.

値型にcustom initializerを作るとdefault initializerにアクセスできなくなります。

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.



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.

deinit を自分で呼んではいけません。

Automatic Reference Counting

Weak References

Property observers aren’t called when ARC sets a weak reference to nil.

またProperty observersの罠ですね。

Optional Chaining

Accessing Subscripts of Optional Type

var testScores = ["Dave": [86, 82, 84], "Bev": [79, 94, 81]]
testScores["Dave"]?[0] = 91
testScores["Bev"]?[0] += 1
testScores["Brian"]?[0] = 72

subscriptもOptional Chainingできるんですね。

Error Handling

Representing and Throwing Errors

In Swift, errors are represented by values of types that conform to the Error protocol. This empty protocol indicates that a type can be used for error handling.


Handling Errors

Error handling in Swift resembles exception handling in other languages, with the use of the try, catch and throw keywords. Unlike exception handling in many languages—including Objective-C—error handling in Swift does not involve unwinding the call stack, a process that can be computationally expensive. As such, the performance characteristics of a throw statement are comparable to those of a return statement.


Type Casting

You can also use type casting to check whether a type conforms to a protocol, as described in Checking for Protocol Conformance.

Type Castingは、Protocolに準拠しているかどうかのチェックにも使えます。

Type Casting for Any and AnyObject

Swift provides two special types for working with nonspecific types:
・ Any can represent an instance of any type at all, including function types.
・ AnyObject can represent an instance of any class type.


Checking Type

Use the type check operator (is) to check whether an instance is of a certain subclass type.



Extensions can add new functionality to a type, but they cannot override existing functionality.


Computed Properties

Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.

Extensionsでstored propertiesやproperty observersを追加することはできません。

Nested Types

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

    extension Int {
        enum Kind {
            case negative, zero, positive
        var kind: Kind {
            switch self {
            case 0:
                return .zero
            case let x where x > 0:
                return .positive
                return .negative



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.

protocolでは、stored propertyを追加することはできませんが、任意の名前のpropertyの実装を強制することができます。メソッドやイニシャライザについても同様です。

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


Class-Only Protocols

You can limit protocol adoption to class types (and not structures or enumerations) by adding the class keyword to a protocol’s inheritance list. The class keyword must always appear first in a protocol’s inheritance list, before any inherited protocols:

    protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
        // class-only protocol definition goes here


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 form SomeProtocol & AnotherProtocol. You can list as many protocols as you need to, separating them by ampersands (&).


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. Optional requirements are available so that you can write code that interoperates with Objective-C. Both the protocol and the optional requirement must be marked with the @objc attribute. Note that @objc protocols can be adopted only by classes that inherit from Objective-C classes or other @objc classes. They can’t be adopted by structures or enumerations.

    @objc protocol CounterDataSource {
        @objc optional func increment(forCount count: Int) -> Int
        @objc optional var fixedIncrement: Int { get }

プロトコルに準拠しても、実装を矯正しないようにするには @objcoptional を付加します。


Naming Type Parameters

Always give type parameters upper camel case names (such as T and MyTypeParameter) to indicate that they are a placeholder for a type, not a value.


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):

    func someFunction<T: SomeClass, U: SomeProtocol>(someT: T, someU: U) {
        // function body goes here


Access Control

Indeed, if you are writing a single-target app, you may not need to specify explicit access control levels at all.

単一ターゲットのアプリを開発する際は、特にaccess control levelsを明示しなくても良いです。

Modules and Source Files

Swift’s access control model is based on the concept of modules and source files.


A module is a single unit of code distribution—a framework or application that is built and shipped as a single unit and that can be imported by another module with Swift’s import keyword.


Access Levels

Marking a class as open explicitly indicates that you’ve considered the impact of code from other modules using that class as a superclass, and that you’ve designed your class’s code accordingly.


Custom Types

A public type defaults to having internal members, not public members. If you want a type member to be public, you must explicitly mark it as such. This requirement ensures that the public-facing API for a type is something you opt in to publishing, and avoids presenting the internal workings of a type as public API by mistake.