【読書感想】SwiftUIたった２日でマスターできる〜前編〜

## はじめに
こんにちは、@taikiti（たいきち）です！

今回は、学習中のSwiftUIについて、参考書から得た知識をまとめていきます。

このあと紹介する参考書やSwiftUIが気になっている方は、ぜひ読んいただければと思います。

ちなみに、想像以上に学ぶことが多かったので、記事は２部構成にしようと思います。


## 学習中の参考書
この記事は「[たった2日でマスターできる iPhoneアプリ開発集中講座](https://www.amazon.co.jp/gp/product/B0BJQ6RN44/ref=ppx_yo_dt_b_d_asin_title_o02?ie=UTF8&psc=1)」で学習した内容のふりかえりとなります。

**要約ではないため、この記事を読むだけではアプリを開発することはできません。**
あらかじめご了承ください。

本書では、「2日でSwiftUIをマスターする」ということを目的としています。（もちろん基礎知識のみ）

1日目と２日目の２部構成になっており、プログラミング経験のある方なら、ちょうど2日で一通り完了できると思います。

僕は、XcodeやSwiftUIをメインに開発したことがなかったので、それぞれの扱い方をざっくり学ぶことができ満足しています。

また、本書の内容はかなり優しいので、プログラミング未経験の方にもオススメです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/ed32f1ee-55c4-4ca1-e41e-11b45f48f4c2.png)

https://www.amazon.co.jp/gp/product/B0BJQ6RN44/ref=ppx_yo_dt_b_d_asin_title_o02?ie=UTF8&psc=1

## Xcodeの設定
### デバッグエリアを表示する

デバッグエリアには、print() でテキストを出力させることができます。
必須レベルでよく使うので、表示されていない場合は設定内容を確認してみましょう。

**①Xcodeの上部のメニューから「Show Debug Area」を選択する**

View → Debug Area → Show Debug Area
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/ec367e67-21da-9159-ea4e-70251c92fdb0.png)

**②赤枠のエリアが表示されていればOK**
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/b9fd7bd9-c3e8-bda8-b358-1ba7a1bdcb96.png)

### ファイルの拡張子を表示する

初期設定だと拡張子が非表示になっていました。
めちゃめちゃ不便なので表示されるように設定を変更しましょう。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/670f7422-7ac7-703e-01e4-7e291d8140c7.png)

**①Xcodeの上部メニューから「Settings…」を選択する**
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/c76e97fc-2cab-34bf-6196-333351b26c7b.png)

**②Generalタブの「File Extensions」の設定を確認する**
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/dae57fd6-5f5a-0089-039f-af01f0905147.png)

**③設定を「Show All」に変更する**
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/cf5a4c53-de67-ffb9-2622-65e6bab44bc2.png)

**④ファイルに拡張子が表示される**
「〇〇.swift」のようになっていればOK！
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/a6863afd-80a9-734c-a3d3-46207dae8bb1.png)


### コードの折りたたみ機能を有効化する

この機能を有効化すると、コードの開始と終了が分かりやすくなります。

ネストが深いときに見やすくなるのでオススメです！

**①先ほどの設定画面から「Text Editing」を選択する**

**②「Code folding ribbon」にチェック**
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/fc6ba6ac-2821-34ec-4f0d-248382b76fdf.png)

**③行数の右側に上下の矢印が表示される**
これで{ }の始まりと終わりが分かりやすくなる！
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/3d7b693f-4f95-f791-82d7-8c07d5ea5169.png)


**④矢印部分をクリックするとコードが折りたたまれれる**
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/d90370b6-960a-cc9b-6167-812e42e50df4.png)

### Canvasを表示する

Canvasでは、開発中の画面をiPhoneなどのプレビューで確認できます。

**①適当な.swiftファイルを選択する**
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/d5b21337-12cc-9b65-043c-3e562f9fa690.png)

**②右側の横線のアイコンをクリックするとメニューが表示される**
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/f9fd7010-feb2-8fa2-aaa8-2782e8bca426.png)

**③「Canvas」を選択する**
左側にチェックが入る。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/50153abf-5e4e-1997-5abf-ce39b864416a.png)

**④Canvasが表示されればOK**
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/ca9dd4fb-808e-6f3c-1ed2-407608f2fc92.png)

### コードを整形する
カーソルを置いている１行が整形されます。
```swift
「ctrl + i」
```
全体を整形する場合には「cmd + a」などで全選択してからショートカットで整形します。

ただ、インデントの位置は直るけど、改行の位置はズレてるままだったりするので精度は低いのかな〜という印象。

VSCodeの拡張機能みたいに細かなルールを設定できたりするんだろうか。

### Selectableボタン

Canvasの下部にある矢印マークが『Selectableボタン』です。
※青くなってるところ
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/3c6faffb-815d-459e-b7b3-7076dae30e6d.png)

オンにすると、以下のようなことが可能になります。

- コードから該当する画面の箇所を選択
- 画面からコードを選択

↓↓サンプル画面で動きを確認してみました↓↓

**①「キーワードを入力してください」を選択する**
選択した箇所がCanvas上で青く囲まれます。
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/9ee33270-108b-aec2-aa10-4ec3efd1b6b0.png)

**②コード側では該当箇所が自動で選択されている**
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/7bd91d64-73bc-920f-bed7-d32f82033262.png)

１つの画面に部品が増えてきた時とか、コードが複雑になった時に便利ですね！
ちなみに、①と②を逆に実施することもできます。

### Libraryを起動する

『Library』とは、SwiftUIで使えるパーツ集のようなもの、と理解しました。

**①どこかにカーソルを置く**
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/48af483a-ce33-15fc-8744-32c21bee5f5a.png)

**②ショートカット「shift + cmd + L」でLibraryを表示する**
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/a832ad7a-012c-26b9-09e9-4ef6d811dfa5.png)

**③追加したい項目を選択するとコードが挿入される**
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/a6540e63-f2ce-b0b0-e189-e71b8bed8f7b.png)

## じゃんけんアプリの学び

### プロジェクトファイルの役割

Xcodeでプロジェクトを作成したときに用意されているファイルたちの簡単な役割。

| ファイル名 | 役割 |
| --- | --- |
| 〇〇App.swift | アプリの実行はこのファイルから最初に行われる |
| ContentView.swift | アプリの画面 |
| Assets.xcassets | アイコン、画像、音楽ファイルなどを格納する |

### Assets.xcassets の 1x、2x、3x とは

画像ファイルを置くと以下のようになる。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/c1ef243d-d021-deb0-a637-110f3c7dbd73.png)

iPhoneはシリーズごとにスケールが異なり、1x、2x、3xのうち最適なサイズの画像が使用される。

例えば、スケールが3xの端末にも関わらず1xの画像しか用意していない場合、1xの画像が3xのサイズまで引き伸ばされて使用されるため画質が劣化する。

### こまめにビルドして文法をチェック

ショートカット「cmd + B」でビルドして、文法に誤りがないかチェックした方がいいです。

### 数値の範囲の書き方

1…3 のように数値の範囲を指定できます。

```swift
// 上限値３を含む場合
Int.rendom(in: 1...3)

// 上限値３を含まない場合
Int.random(in: 1...<3)
```

### repeat文

以下の例では、条件に該当する間、1〜３の数値が n に格納されます。

```swift
repeat {
    // 実行するコード
    var n = Int.rendom(in: 1...3)
} while 繰り返しの条件
```

### アプリアイコンの設定方法

**①Assets.xcassets のAppIconに「1024x1024」の画像を配置する**
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/f3a94025-f8a0-708c-8574-5cfc1ba0d8a7.png)

**②アイコンを設定すると、シミュレーターや実機でビルドした時のアイコンが設定した画像になる**
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3329686/0073284f-5bc5-5dd3-3e9c-de67ea34fa31.png)

## 楽器アプリの学び

### 音楽ファイルを再生する

AVFoundation を使用する。

具体的な使い方はいろんなサイトを見た方がいいかも。

```swift
import AVFoundation
```

### クラスとインスタンス

クラスは機能集、インスタンスは機能の実体化。

```swift
// クラス
class SampleSound {
	// 音源データの読み込み
	let sampleData = NSDataAsset(name: "sampleData")!.data
	
	// サンプルデータ再生用の変数
  var samplePlayer: AVAudioPlayer!
	
	// 使いたい機能 
	func samplePlay() {
        do{
            // サンプルデータ再生用の変数に、音源データを指定
            samplePlayer = try AVAudioPlayer(data: sampleData)
            
            // サンプル音源再生
            samplePlayer.play()
        } catch {
            print("音源再生で、エラーが発生しました！")
        }
    }
}
```

クラスをインスタンス化することで、クラスに定義したメソッドを使用することができます。

```swift
// インスタンス
// 音を出すため、SampleSoundクラスをインスタンス化
let samplePlayer = SamplePlayer()

// 音を出す
samplePlayer.samplePlay()

```
こんな感じで、「インスタンス.メソッド」の形で使えます。

### オプショナル型とアンラップ

**オプショナル型とは**

型の後ろに「?」をつけるだけ。
```swift
var n = Int?
```
このときの n には、値があるかもしれないし、ないかもしれない。

**アンラップとは**

オプショナル型の場合には、値があるかどうかをチェックして使用する必要があります。（→アンラップ）

```swift
// n の値を ok に格納し、値があればif文の中の処理が実行される。
if let ok = n {
		print("値あるよ：\(ok)")
}
```

「!」をつけることで、強制アンラップして無理やり使用することもできます。

```swift
// ok に値がなくても実行できる
print("値あるよ：\(ok!)")
```

値がなくても実行はできますが、エラーになってしまいます。

強制アンラップをするためには、値があるという保証（値があることが明確であること）が必要。

## マップ検索アプリの学び

### 地図を使用する

アプリで地図や衛生画像の表示、ピンの位置、住所から座標の検索ができます。

```swift
import MapKit
```

CLGeocode rクラスを使うと緯度経度から住所を検索できる。

また、住所から緯度経度を検索することも可能。

```swift
// CLGeocoderインスタンス生成
let geocoder = CLGeocoder()

// 入力された文字から位置情報を取得
geocoder.geocodeAddressString(
    searchKey,
    completionHandler: { (placemarks, error) in
        // リクエストの結果が存在するとき
        if let placemarks,
					 // 1件目の情報を取得
           let firstPlacemark = placemarks.first,
					 // 位置情報を取り出す
           let location = firstPlacemark.location {
           // 位置情報から経緯と緯度を取り出す
           let targetCoordinate = location.coordinate
           // 経緯と緯度をデバッグエリアに表示
           print("経緯と緯度：\(targetCoordinate)")
        }
})
```

geocodeAddressStringは住所やランドマークの文字列をAppleのサーバーに問い合わせて位置情報を取得する役割を持っている。

位置情報の取得が完了したときに、completionHandlerが実行される。

このとき、引数のplacemarksに位置情報が格納され、errorにはエラーが格納されます。

### クロージャ（無名関数）とは

位置情報の取得に使用した先ほどのコードでは、クロージャという仕組みを使用している

```swift
geocoder.geocodeAddressString(
    searchKey,
/** この部分がクロージャ***************************/
    completionHandler: { (placemarks, error) in
				// 実行したいコード
		}
/**********************************************/
)
```

クロージャでは、特定の条件が揃うと自動で処理が実行される。

### 構造体とは

struct のこと。

```swift
// 果物を管理する構造体
struct Fruit {
	// プロパティ
	var fruit1: String
	var fruit2: String
  // 果物を合わせた文字列を作るメソッド
	func allFruit() -> String {
		return fruit1 + "と" + fruit2
	}
} 

// 使い方
var goodFruit = Fruit(fruit1: "レモン", fruit2: "オレンジ")
print(goodFruit.allFruit) // レモンとオレンジ
```

プロジェクト作成時からある ContentView.swift なども同じ構成です。

変数を定義するとプレビューでエラーになるのは、実行するのに値が必要になるから。

### イニシャライザとは

受とった引数によって、実行されるイニシャライザ(init)が異なる。

```swift
// 名前の管理
struct MakeName {
    var fullName: String
    var name: String

		// 処理①
    init(string1: String, string2: String) {
        fullName = string1 + string2
        name = ""
    }
    
		// 処理②
    init(string1: String) {
        fullName = ""
        name = string1
    }
}

var sampleName = MakeName(string1: "たろう")
print(sampleName.name) // たろう
var sampleName2 = MakeName(string1: "たなか", string2: "たろう")
print(sampleName.fullName) // たなかたろう
```

引数に string1 と string2 を指定した場合、処理①が実行されます。

引数に string1 だけを指定した場合、処理②が実行されます。

### おわりに

簡単ですが以上となります。

参考書を読んでないと分からないような内容になってしまった気もしますが...。

少しでも内容が気になった方は参考書を手に取っていただければと思います！

次回は２日目の内容について、要点を整理していきます。

SwiftUIに限らず、新しいことするの楽しいな〜