[iOS]Closureと非同期処理の超基本（初学者向け）

超基本部分を平易に書きます
難しいことは混乱するので書きません
ハマりどころも書きます

### 対象

初学者向けの基礎部分です
１冊参考書読んだくらいのレベルを想定しています（関数、引数くらいはわかる人）

### なぜアプリで非同期処理が重要か

スマホアプリのプログラムというのは大抵の場合一瞬で処理が終わってしまいます
でも実際に利用する実環境では、様々な理由で待ちが発生します

・アニメーション
・サーバーとの通信
・重たい処理、生成

アプリを作っているとこれらを避けて通るのが難しいです
すると「終わってから何かをしたい」というケースが頻発します

## 分かりやすい非同期処理とClosure

以下は0.3秒でアニメーションをする関数です
animateという関数には、duration,animations,completionという3つの引数があります
アニメーション処理が終わったらcompletionが呼ばれます

```swift

UIView.animate(withDuration: 0.3, animations: {
    // ここでアニメーション処理
}, completion: { (finished:Bool) in
    // アニメーション終了後の処理
})

```

このうち、animationsとcompletionがClosureです
animationsを0.3秒で実行して、その後completionを呼びます

### Closureとは何か

SwiftにおけるClosureとは**関数オブジェクト**の一種です（by wikipedia）
平たく言えば関数を変数にしたものです

何が嬉しいかと言えば、非同期処理をしたいときに便利になります
「処理Aが終わったときに処理Bをしたい」
この処理BをClosureで定義します
先程のアニメーションの例なら、処理BはCompletionです

**処理Bは関数でもいいじゃないか**、と思うかもしれません
**もちろん実際にそういう作り方もできます**し昔はClosureが無かったため、そちらが主流でした
しかしClosureの方が何かと便利なことが多く、Swiftの時代からはClosureが多用されています

### Closureが混ざると、処理の順番で混乱する

Closureがないと、大抵は処理が上から順に実行されるのでイメージしやすいと思います
しかしClosureが入ってくるとそれが前後するので注意しなければなりません

```swift
func myAnimation() -> Int {
    
    // １番目
    
    UIView.animate(withDuration: 0.3, animations: {
        // アニメーション
    }, completion: { (finished:Bool) -> Void in
        // 終了後の処理　３番目
        // return 1    <-- これは間違い
    })
    
    // ２番目
    
    return 0
    
}

```

上記において、処理順は①②③の順です（animationsの中はややこしくなるので無視してください）
今、②はcompletionより前に実行されます。myAnimationのreturnを③に書くのは間違いです
Closureは関数と同じなので、**Closureに対してreturnができます**

>completion: { (finished:Bool) -> Void in

このVoidが戻り値の型です（普段は省略されます）

### Closureから値を返す

誰しも通る道だと思いますが、Closureを覚えるとこういう処理を書いてしまいます

```swift

func myFunc() {
    // myAnimationの結果をprintしたい
    let result = myAnimation()
    print(result)
}

```
completionで処理をした後に、その値を用いて次の処理をしたいことがあります
しかし先程書いたように、completionの値をreturnで返すことはできません

次に考えることは、myFunc() → myAnimation() → completionと来たのだから、そこから逆に返していく方法です。**completionから値を得て**、それをmyAnimationで返せるように工夫すればと頭を捻ります

しかしそれもできません
ここでのcompletionはあらかじめ定義されたものなのでIntを返すように変更はできません

そしてなにより、**closureが値を返した時には既にprintが終わってしまっています**

なので、completionから結果を得るには例えばこうします

```swift

/// CompletionClosureというClosureの型を定義
typealias CompletionClosure = ((_ result:Int) -> Void)

func myFuncC() {
    
    // １番目
    myFuncD(completionClosure: { (result:Int) in
        // ６番目 10が返ってくる
        print(result)
    })
    
    // ４番目
}
func myFuncD(completionClosure:@escaping CompletionClosure) {
    // ２番目

    UIView.animate(withDuration: 0.3, animations: {
        // アニメーション
    }, completion: { (finished) in
        // ５番目
        
        // 終了した時、10という値を返す
        completionClosure(10)
    })
    
    // ３番目
}


```

何をやっているかというと、自分で新しくClosureの型を定義して、それを「終わったらこれを呼び出して」と渡してやります
一見するとトンデモなくややこしく見えます
私も最初はそうでしたが、使っていくととても便利なものだと分かります
ただ処理順序はこのように混乱しがちなので、処理を複雑にしないよう注意を払わなければなりません。

### 別解1.終わるまで待つ

詳しくは書きませんが、アニメーションが終わるまで処理を待つ方法ももちろんあります
しかし主流ではありません
理由は幾つかあります

- 結局処理が複雑になる
- 不具合があると完全に処理が止まってしまう
- 処理を止めると不都合が生じる

本当にどうしても値を直接化したい時や、複数の非同期処理が混ざる時に使うことが多いと思います

### 備考その他

**Q. XcodeでClosureを書いたら書式が違う**

それは省略形です
今回は省略しない形を自分で打ち込んでいます（省略されるとパット見で何か分からなくなるので）
Closureは色んな省略形があります
複雑なので大変ですが調べてください
fucking closure syntaxとググるとたくさん見つかります

**Q. delegateと存在意義がかぶっている?**

歴史的な経緯です
両方使いますが、自分で定義するならClosureの方が最近主流な気がします（2018年）

## あとがき

教科書やちゃんとしたドキュメント読むとここらへん混乱しますよね
書式とかではなく、何に使うか、何で必要か、挙動を確認したほうが早い気がします

#### メモ

これQ&Aサイトの回答用に書いたんですが、細部の用語について少し自信がありません
問題があれば微修正していくつもりです

あわせて読みたい（自分が）
[非同期処理ってどういうこと？JavaScriptで一から学ぶ](https://qiita.com/kiyodori/items/da434d169755cbb20447)
[JavaScriptの非同期処理を並列処理と勘違いしていませんか？](https://qiita.com/klme_u6/items/ea155f82cbe44d6f5d88)