Swift 5.1 Tour まとめ

# 概要
Swift開発経験0.001程度のプログラマーが少しでもSwift理解を深めるために[A Swift Tour](https://docs.swift.org/swift-book/GuidedTour/GuidedTour.html)の内容をまとめました。

ただ、そもそもツアーだけでは理解をすることができない点が多々あったので、自分で追記したり、参考記事のリンクを添付しています。
そのため完全なSwiftTourのただのまとめではなく自分なりにアレンジを加えたものになります。
まとめといったな？[あれは嘘だ](https://dic.pixiv.net/a/%E3%81%82%E3%82%8C%E3%81%AF%E5%98%98%E3%81%A0)

※Tourで使われているコードはそのまま添付しています。検証の際は[MyPlayground](https://qiita.com/egplnt/items/7454344f543351a68315)のご利用をおすすめします。

# 本文
## Simple Values

### 変数と定数

変数は`var`で、定数は`let`で定義する。

```swift

// 変数を定義
var myVariable = 42
myVariable = 50 // 上書き

// 定数を定義
let myConstant = 42
myConstant = 11 // エラーになる
```

以下の形式で、変数や定数に型を明示することができる。

```swift

let explicitDouble: Double = 70 // コロンの後のDoubleが型の定義。
```

※型の一覧と意味は[こちら](https://thinkit.co.jp/article/13218)を参照。

下記のように変数の結合で、型がマッチしていない場合、エラーになるので注意。

```swift

let label = "The width is " // 文字列はダブルクオーテーションで囲む
let width = 94
let widthLabel = label + String(width) // widthがInt型のため、string型に変換
```

文字列内で変数を展開する場合は`\()`で変数を囲う。

```swift

let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
```

### 配列と辞書

配列型と辞書型の値は`[]`で囲う。 ([配列と辞書について](https://qiita.com/wrdlisner/items/fca72e2cbf5b41bdb897))

```swift

// 配列
var shoppingList = ["catfish", "water", "tulips"]
shoppingList[1] = "bottle of water"
// 配列に追加
shoppingList.append("blue paint")

// 辞書
var occupations = [
    "Malcolm": "Captain",
    "Kaylee": "Mechanic",
]
// 辞書の追加
occupations["Jayne"] = "Public Relations"
```

※辞書型はPHPでいう連想配列といったところか。
※辞書型については[こちら](https://www.sejuku.net/blog/31390)も参照。

空の配列型、辞書型の定義もできる。

```swift

// 空配列
let emptyArray = [String]() // 値の型を定義
// 空辞書
let emptyDictionary = [String: Float]() // キーと値の型をそれぞれ定義
```

すでに定義されている配列・辞書の初期化は以下のように書く。

```swift

// 配列の初期化
shoppingList = []
// 辞書の初期化
occupations = [:]
```

## Control Flow

条件は`if`や`switch`で、ループは`for-in`や `while`、 `repeat-while`で書く。

```swift

let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
// inの後にループさせる変数を置く
// forの後のteamScoreにループの結果取得できる値が格納される
for score in individualScores { 
    if score > 50 {
        teamScore += 3
    } else {
        teamScore += 1
    }
}
print(teamScore)
// Prints "11"
```

詳しくは[こちら](https://qiita.com/funafuna/items/4da8016b2d1e13cec538)も参照。

### オプショナル型と`if let`

[オプショナル型](https://qiita.com/takutoki/items/321ab4686486f74bd039)は、変数の型のひとつで、[**nil**](https://qiita.com/solty_919/items/d2b10bf57b27f892144a)の可能性がある値を指す。
`nil`が考えられるような変数をチェックする場合、`if let`を使うと良い。

```swift

var optionalName: String? = "John Appleseed" // オプショナル型変数
var greeting = "Hello!"
// optionalNameがnilのとき、条件節内は通らない。(falseのため)
if let name = optionalName {
    greeting = "Hello, \(name)"
}
```

`optionalName`の定義で使われている`String`の後の`?`で、[オプショナル型](https://www.sejuku.net/blog/35070)を定義。

下記のように`??`を使って文字列内でnilかどうかの判定をすることもできる。

```swift

let nickName: String? = nil
let fullName: String = "John Appleseed"
// nickNameがnilなら、fullNameが使用される
let informalGreeting = "Hi \(nickName ?? fullName)"
```

### switch構文

`switch case`を使えば、いろいろなかたちでの比較ができる。

```swift

let vegetable = "red pepper"
switch vegetable {

    // 文字列の比較。一致していたら「Add some raisins and make ants on a log.」が表示される。
    case "celery":
        print("Add some raisins and make ants on a log.")

    // 同じ結果を出力する場合、比較対象をカンマで区切って書くこともできる。
    case "cucumber", "watercress":
        print("That would make a good tea sandwich.")

    // 変数xが「pepper」という文字を含む場合、letの後の定数xに「pepper」を格納する
    case let x where x.hasSuffix("pepper"):
        print("Is it a spicy \(x)?")

    // defaultを設定しないとエラーになる
    default:
        print("Everything tastes good in soup.")
}
// Prints "Is it a spicy red pepper?"
// 上記いずれかのcaseに合致すれば、switch構文は終了する。
// ※caseに一致しない場合、defaultが出力される。
// (続くcaseが比較されることはない)
```

### for-in構文

`for in`を使えば、ループ対象の配列・辞書のキーと値のそれぞれを取り出せる。

```swift

// 辞書型
let interestingNumbers = [
    "Prime": [2, 3, 5, 7, 11, 13],
    "Fibonacci": [1, 1, 2, 3, 5, 8],
    "Square": [1, 4, 9, 16, 25],
]
var largest = 0
// kindで「Prime」などのキーを、numbersで配列を取り出せる
for (kind, numbers) in interestingNumbers {
    for number in numbers {
        if number > largest {
            largest = number
        }
    }
}
print(largest)
// Prints "25"
```

### while構文

while構文は、while後に書かれた条件に該当する限り構文内を通る。

```swift

var n = 2
while n < 100 {
    n *= 2
}
print(n)
// Prints "128"
```

`for 変数 in 開始値 ..<　終了値`で、`＋1`ずつ変数に格納され、変数が終了値と同値の場合、条件節内を通らない。

```swift

var total = 0
for i in 0..<4 {
    total += i
}
print(total)
// Prints "6"
```

※`for 変数 in 開始値 ... 終了値`は、終了値と同値でも条件節内を通り、超過した場合falseとなり、条件節内を通らない。

### Functions and Closures

functionは`func`で始めて定義する。

```swift

func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
// functionの実装
greet(person: "Bob", day: "Tuesday")
```

`person`と`day`が引数にあたるラベルであり、それぞれのラベルのコロンの後の`String`が値の型を表す。
`->`後の`String`は、返り値（戻り値）の型を表す。
また、`_`のみ記述してラベルを省略することも可能。

```swift

func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
// 「_」を用いることで、第一引数はラベルが不要。
greet("John", on: "Wednesday")
```

### タプル

返り値は[タプル](https://qiita.com/funafuna/items/329143aa3983a5f56ec4)を使って[複数指定](https://qiita.com/ohkawa/items/a7e5b9acc2aadba1d659)することも可能。

```swift

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.sum)
// Prints "120"
print(statistics.2)
// Prints "120"
```

### ネスト

関数をネスト（入れ子）構造で書くこともできる。

```swift

func returnFifteen() -> Int {
    var y = 10
    func add() {
        // 上位の関数で定義された変数にアクセスすることもできる
        y += 5
    }
    add()
    return y
}
print(returnFifteen())
// 15
```

### ファーストクラスオブジェクト

Swiftでは関数は「[ファーストクラスオブジェクト](https://thinkit.co.jp/article/15184)」として定義されている。
よって、値として関数を用いることもできる。

```swift

func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)
```

また、引数に関数を入れることもできる。

```swift

func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
    for item in list {
        if condition(item) {
            return true
        }
    }
    return false
}
func lessThanTen(number: Int) -> Bool {
    return number < 10
}
var numbers = [20, 19, 7, 12]
// 第二引数でlessThanTenという関数を用いている
hasAnyMatches(list: numbers, condition: lessThanTen)
```

### クロージャ

[クロージャ](https://www.sejuku.net/blog/34503)は、たとえば次のように書く。

```swift

var numbers = [20, 19, 7, 12]
let mappedNumbers = numbers.map({ number in 3 * number })
print(mappedNumbers)
// Prints "[60, 57, 21, 36]"
```

他にも、`in`などを省略することができる。

```swift

var numbers = [20, 19, 7, 12]
let sortedNumbers = numbers.sorted { $0 > $1 } // $0と$1については下記のクロージャの記法について参照を
print(sortedNumbers)
// Prints "[20, 19, 12, 7]"
```

※クロージャの記法については[こちら](https://qiita.com/saenuruki/items/19c304d7940f6ea4a293)を参照

## Objects and Classes

クラスの定義は`class`で始める。

```swift

class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
```

定義したクラスは以下のように用いる。

```swift

var shape = Shape()
// ShapeクラスのnumberOfSides変数に 7 を格納
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
print(shapeDescription)
// A shape with 7 sides.
```
### イニシャライザ

インスタンスの生成時、イニシャライザ`init`での初期化をする必要がある。
※その理由については[こちら](https://qiita.com/shtnkgm/items/8b7979fc84a3cc065238)。

```swift

class NamedShape {
    var numberOfSides: Int = 0
    var name: String
    // name初期化 イニシャライザのため、funcは不要
    init(name: String) {
        // selfで自クラス内の変数を指示する。（initのnameを指していない）
        self.name = name
    }

    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}
```

オブジェクトのクリーンアップ処理をする場合、`deinit`で[デイニシャライザ](https://swift-ios.keicode.com/lang/deinitializer.php)を生成する。

### 継承

[`継承`](https://tea-leaves.jp/swift/content/%E7%B6%99%E6%89%BF)の概念があり、親クラスの属性を引き継ぐためには、子クラスの後に`: 親クラス`を記載する。

```swift
// SquareがNamedShapeクラスを継承
class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func simpleDescription() -> String {
        return "A square with sides of length \(sideLength)."
    }
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
```

親クラスにある関数と同一の関数名を用いる場合、`override`をつけて定義。（なければエラーになる。）

### ゲッター・セッター

[ゲッターとセッター](https://qiita.com/yuinchirn/items/c1bc87494cb758a6b0ca)を利用することもできる。

```swift

class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }

    var perimeter: Double {
        // 値の取得
        get {
            return 3.0 * sideLength
        }
        // 値のセット
        set {
            sideLength = newValue / 3.0
        }
    }

    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
print(triangle.perimeter)
// Prints "9.3" ゲッター
triangle.perimeter = 9.9
print(triangle.sideLength)
// Prints "3.3000000000000003" セッター
```

上記の`EquilateralTriangle`クラスでは、3つのステップが踏まれている。

* サブクラスが宣言するプロパティの値をセット
* サブクラスのイニシャライザの呼び出し
* スーパークラス（親クラス）で定義されたプロパティの値を変更。

### willSet と didSet

`willSet` `didSet`でプロパティの変更前、変更後で何らかの処理を行わせることができます。

```swift

class TriangleAndSquare {
    // 先のEquilateralTriangleクラスを定義
    var triangle: EquilateralTriangle {
        willSet {
            // newValueはwillSetの定数
            square.sideLength = newValue.sideLength
        }
    }
    // 先のSquareクラスを定義
    var square: Square {
        didSet {
            // oldValueはdidSetの定数
            triangle.sideLength = oldValue.sideLength
        }
    }
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
print(triangleAndSquare.square.sideLength)
// Prints "10.0"
print(triangleAndSquare.triangle.sideLength)
// Prints "10.0"
triangleAndSquare.square = Square(sideLength: 50, name: "larger square")
print(triangleAndSquare.triangle.sideLength)
// Prints "10.0"
```

結果がオプショナル型の場合があるとき、`Square?`のように`?`をつける。
オプショナル型の変数ないし定数を利用する際は、`optionalSquare?`のように対象のプロパティの後に`?`をつける。

```swift

let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
```

## Enumerations and Structures

### [enum](https://qiita.com/hachinobu/items/392c96820588d1c03b0c)
列挙型を書く際は、`enum`で始める。

```swift

enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king
    // 列挙型でも関数を書くこともできる
    func simpleDescription() -> String {
        switch self {
        case .ace:
            return "ace"
        case .jack:
            return "jack"
        case .queen:
            return "queen"
        case .king:
            return "king"
        default:
            return String(self.rawValue)
        }
    }
}

let ace = Rank.ace
print(ace)
// ace

let aceRawValue = ace.rawValue // rawValueで要素の値を取得
print(aceRawValue)
// 1
```

列の要素それぞれの値は、先頭から`0`、`1`、`2`...というように順番に割り当てられる。
(例：`case a, b, c`という列なら、`a`には`0`が、`b`には`1`、`c`には`2`が割り当てられる。)

ただ、`case ace = 1`のように要素に対して明示的に値を割り当てることによって、要素の値を変更することができる。
(例：`case ace = 1`では明示的に`1`を要素の値に割り当てていますが、そうでなければ`0`が入る。)

また、続く要素の値は2、3...というように明示された値に続く。

```swift

if let convertedRank = Rank(rawValue: 3) {
    let threeDescription = convertedRank.simpleDescription()
}
```

上記のようにインスタンス生成時にrawValueを指定して列挙子を取得する際、自動的にイニシャライザー`init(rawValue:)`が付与される。

```swift

enum Suit {
    case spades, hearts, diamonds, clubs

    func simpleDescription() -> String {
        switch self {
        case .spades:
            return "spades"
        case .hearts:
            return "hearts"
        case .diamonds:
            return "diamonds"
        case .clubs:
            return "clubs"
        }
    }
}
let hearts = Suit.hearts
let heartsDescription = hearts.simpleDescription()

```

自クラス外の特定の要素にアクセスする場合は、`Suit.hearts`のように要素の前に`Suit`をつける必要があるが、クラス内では`.hearts`のようにクラスを省略できる。
switch文の`self`で、引数自体にアクセスできる。

下記のように要素を定数に格納し、要素と一致する値を抽出することもできる。

```swift

enum ServerResponse {
    case result(String, String)
    case failure(String)
}

let success = ServerResponse.result("6:00 am", "8:09 pm")
let failure = ServerResponse.failure("Out of cheese.")

switch success {
case let .result(sunrise, sunset):
    print("Sunrise is at \(sunrise) and sunset is at \(sunset).")
case let .failure(message):
    print("Failure...  \(message)")
}
// Prints "Sunrise is at 6:00 am and sunset is at 8:09 pm."

```

### 構造体

`struct`をつけて[構造体](https://qiita.com/yuinchirn/items/98b568d595650eca3334)を生成できる。イニシャライザを持つことができるが、継承することはできず、クラスが参照型であるのに対し、構造体は値型。

```swift

struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .three, suit: .spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()

```

## Protocols and Extensions

[プロトコル](https://qiita.com/abouch/items/67f9def6dc2feec3e183)は以下のように定義する。

```swift
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()
}
```

クラスも列挙も構造体もプロトコルを継承することができる。

```swift

class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 69105
    func adjust() {
        simpleDescription += "  Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
```

`mutating `は`struct`や`enum`において自身の値を変更する場合に`func`の前につける。(変更できることを明示する必要がある)
`class`ではつける必要がない。クラスは常に変更できるから。

### [extension](https://www.sejuku.net/blog/33334)

```swift

extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
print(7.simpleDescription)
// Prints "The number 7"
```

`extension`をつけると既存の機能を拡張できる。
上記の例でいうと、`ExampleProtocol`の型プロパティを`Int`で拡張し、`adjust`メソッドを`ExampleProtocol`に追加している。

```swift

let protocolValue: ExampleProtocol = a
print(protocolValue.simpleDescription)
// Prints "A very simple class.  Now 100% adjusted."
// print(protocolValue.anotherProperty)  // Uncomment to see the error

```
プロトコル名は型としても利用できる。
また上記の例では、`protocolValue `変数はすでに`SimpleClass`クラスで利用されているが、コンパイラが`ExampleProtocol`の変数として認識するため問題ない。クラスが実装するプロパティにアクセスできない。

## Error Handling

エラーを取得する際は`Error`プロトコルを用いる。

```swift

enum PrinterError: Error {
    case outOfPaper
    case noToner
    case onFire
}
```

エラーハンドリングは`throw`を用い、エラーハンドリングをする関数を用いる場合は`throws`を用いる。

```swift

func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    return "Job sent"
}
```

下記の例ではIf節を通った場合、即座にエラーを返す。

```swift
func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    return "Job sent"
}
```

エラーハンドリングの方法は他にもある。

### do-catch

```swift

do {
    let printerResponse = try send(job: 1040, toPrinter: "Bi Sheng")
    print(printerResponse)
} catch {
    print(error)
}
// Prints "Job sent"
```

`do-catch`では、`do`ブロック内で`try`文を書くことで、エラー時に`catch`のエラーコードが自動的に出力される。

下記のように複数の`catch`ブロックを用意することも可能。

```swift


do {
    let printerResponse = try send(job: 1440, toPrinter: "Gutenberg")
    print(printerResponse)
} catch PrinterError.onFire {
    print("I'll just put this over here, with the rest of the fire.")
} catch let printerError as PrinterError {
    print("Printer error: \(printerError).")
} catch {
    print(error)
}
// Prints "Job sent"
```
### try?

`try?`と書けばオプショナル型で結果を返せる。関数がエラーを返せば、結果では`nil`が返る。

```swift

let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler")
let printerFailure = try? send(job: 1885, toPrinter: "Never Has Toner")
```

### [defer](https://qiita.com/funafuna/items/cd48016553184c7d2104)

`defer`を使ってブロック要素を書くことで最終的には関数内のコードをすべて通す。（returnするまで）

```swift

var fridgeIsOpen = false
let fridgeContent = ["milk", "eggs", "leftovers"]

func fridgeContains(_ food: String) -> Bool {
    fridgeIsOpen = true
    defer {
        fridgeIsOpen = false
    }

    let result = fridgeContent.contains(food)
    return result
}
fridgeContains("banana")
print(fridgeIsOpen)
// Prints "false"
```

## Generics

[ジェネリクス](https://qiita.com/ktaguchi/items/fc260a0af506f258177d)で、IntやStringなどの予め指定された型とは異なり、任意の指定した型パラメータを用いることができる。
`<>`(山括弧)で括ることで、ジェネリクスの関数・型を定義することができる。
※下記でいうと`<Item>`がジェネリクス。

```swift

func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result = [Item]()
    for _ in 0..<numberOfTimes {
        result.append(item)
    }
    return result
}
makeArray(repeating: "knock", numberOfTimes: 4)
```

ジェネリクスは、クラス、列挙、構造体でも用いることができる。

```swift

// Reimplement the Swift standard library's optional type
enum OptionalValue<Wrapped> {
    case none
    case some(Wrapped)
}
var possibleInteger: OptionalValue<Int> = .none
possibleInteger = .some(100)
```

### where

下記のように`where`を関数内部の前に記述することで、2つの型が同じであること、またはあるクラスがスーパークラスを継承していることを明示することができる。

```swift

func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
    where T.Element: Equatable, T.Element == U.Element
{
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])
```
`<T: Equatable>`と、`<T> ... where T: Equatable`は同じ意味。

End

# 最後に
先人の知恵を勝手にたくさん拝借しました。ありがとうございます。
（リンク先の記事がどれもわかりやすく、理解に際して非常にありがたかったです…）

修正や参考資料などございましたらご指定いただけますと幸いです。

ご覧くださいましてありがとうございました。