簡単なアプリを作成する

この記事は[dots.女子部- 新年度LT大会！#dotsgirls](https://eventdots.jp/event/617141)で行うライブコーディングの内容になります。このライブコーディングでは以下の点に重点を置きました。

* 初心者でも簡単にちょっとしたアプリは書けるということを学ぶ
* UIStackViewを使って簡単にUIを作成できるということを学ぶ
* Timerを使った時間駆動の処理について理解する

ということでタイマーアプリをライブコーディングします。5分間なのでちゃちゃっと作ります。

# 完成図

こんなかんじのタイマーアプリを作ります（横に書いているのは比率です）。
![スクリーンショット 2017-04-04 13.50.54.png](https://qiita-image-store.s3.amazonaws.com/0/100736/6a4c48db-cb70-4098-2f25-eac83ec7a1ac.png)

等間隔で並べる部分が多いのでUIStackViewを使ってUIを作ろうと思います（UIStackViewに関しては後ほど追記しようと思います）。

# バージョン情報

Swift：3.0.1
Xcode：8.2.1

# ライブコーディング内容
## プロジェクトを作成する

Xcodeを立ち上げてプロジェクトを作ります。
![スクリーンショット 2017-04-02 23.51.45.png](https://qiita-image-store.s3.amazonaws.com/0/100736/a3c0674b-67c6-0ec6-60bc-b8ff12936138.png)
今回特に複雑なことはしないのでSingle View Applicationを選択します。
![スクリーンショット 2017-04-02 23.54.24.png](https://qiita-image-store.s3.amazonaws.com/0/100736/19e4e526-baa6-77f4-3fc6-a1e9d3a4f517.png)
適当にプロジェクト名を決めて、プロジェクトの置き場所を設定したら準備完了です。
![スクリーンショット 2017-04-02 23.56.09.png](https://qiita-image-store.s3.amazonaws.com/0/100736/6a868072-6099-68ba-52f9-bcd21da32402.png)

この状態で実行（左上の▶マークをクリック）をすると（まだ何もしてないので）白い画面が出てきます。
![スクリーンショット 2017-04-03 0.04.27.png](https://qiita-image-store.s3.amazonaws.com/0/100736/ecb71e06-57b5-9bfc-d9ab-a4f347366337.png)
ということでまずはUIから作って、その後ロジックを書こうと思います。

## UI部品を配置する

今回、storyboardというものを使ってGUIでUIを作成します。Main.storyboardというファイルをクリックするとこのような画面になります。赤枠の部分がアプリを起動した時に最初に表示される画面です。ここにUI部品を乗せていきます。
![スクリーンショット 2017-04-03 0.14.13.png](https://qiita-image-store.s3.amazonaws.com/0/100736/059cf6c8-65b7-9055-36ae-7b7f6e4e1f78.png)

まずはUIStackViewを配置したいので右下の検索窓から探し出し、ドラッグ&ドロップします（UIStackViewが何なのかについては後ほど追記します）。
![スクリーンショット 2017-04-03 0.22.52.png](https://qiita-image-store.s3.amazonaws.com/0/100736/d50cb0d2-ad1c-fe73-6344-ff4de588ab0d.png)

これだけだとこのUIStackViewが画面のどの位置に配置したらいいのかわからない状況なので、制約を追加します。制約とは例えば「AのviewはBのviewと同じ幅で」などという位置やサイズに関するルールのことを言います。
ではまず左のマージンの制約を追加してみます。
![スクリーンショット 2017-04-03 0.59.59.png](https://qiita-image-store.s3.amazonaws.com/0/100736/e4725e6c-3c47-b947-2e5a-4a3f0ed911b2.png)
StackViewから左に向けてcontrolキーを押しながらドラッグ&ドロップすると上記の表示になります。
左側（Leading）のマージンを調整したいので、Leading Space to Container Marginを選択します。そうすると線が表示されます。SuperViewとこのStackViewの間に制約が追加されていることがわかります。この線を選択すると右側にその制約に関する情報が表示されます。今はマージンが112で設定されているようです。これを10に変更してみます。
![スクリーンショット 2017-04-03 1.30.28.png](https://qiita-image-store.s3.amazonaws.com/0/100736/a0894745-3371-6fe5-c036-4519732458bf.png)
非常に見えづらいのですが、線上に数字が書かれています。制約と描画位置がずれているのでその差分の数値が表示されています。
続けて、上右下にも10のマージンを付けてみます。こんなかんじになりました。
![スクリーンショット 2017-04-03 12.58.14.png](https://qiita-image-store.s3.amazonaws.com/0/100736/54e988ec-6938-a145-ec37-e93616238ba3.png)
せっかくなので制約と描画を一致させてみます。上記画像の右下の方にあるUpdate Framesボタンをクリックします。これで制約通りの描画がされました。
![スクリーンショット 2017-04-03 13.06.38.png](https://qiita-image-store.s3.amazonaws.com/0/100736/32dcc829-2f1a-bc2e-1485-759bed152a8f.png)

ではこのStackViewの中にUILabelとVertical Stack Viewを入れてみます。先ほどと同じように検索して左記オブジェクトを見つけてドラッグ&ドロップで配置します。
StackViewの中に2つ配置されました。高さが等しくなるように配置したいのでStackViewを選択した状態でDistributionをFill Equallyに変更します。
![スクリーンショット 2017-04-03 13.14.36.png](https://qiita-image-store.s3.amazonaws.com/0/100736/30dfc83b-9cf6-44b5-8da8-75394aaadb22.png)

今度はボタンを等間隔で配置します。下半分に配置されているStack Viewにボタンを3つ挿入します。検索窓でUIButtonを検索してドラッグ&ドロップします。
先程と同じようにStack Viewを選択した状態でDistributionをFill Equallyに変更します。これでオブジェクトの配置が終わりました。
![スクリーンショット 2017-04-03 13.21.06.png](https://qiita-image-store.s3.amazonaws.com/0/100736/dd0c3005-e68f-28f1-e94d-8b78ef823dab.png)

## 細かなレイアウト調整をする

* 秒表示の文字をでかくする

Labelを選択した状態で左側のメニューからFontを見つけ出し、数字を変更します。今回は適当に50.0にしました。
![スクリーンショット 2017-04-03 23.32.41.png](https://qiita-image-store.s3.amazonaws.com/0/100736/1c2b8a30-083b-79f6-7bca-6655f98dc77d.png)

* 秒表示を中央寄せにする

同じくLabelを選択した状態にして、左側のメニューからAlignmentを見つけ出し、中央寄せマークをクリックします。
![スクリーンショット 2017-04-03 23.23.50.png](https://qiita-image-store.s3.amazonaws.com/0/100736/db94aae8-bc84-eabe-9fbe-6d111dd92088.png)

* UILabel, UIButtonのデフォルト文字列を指定する

今は「Label」「Button」という文字列が入っているのでそれを変更します。ダブルクリックすれば入力できるようになるのでそれぞれ書き換えてみます。
![スクリーンショット 2017-04-03 23.49.06.png](https://qiita-image-store.s3.amazonaws.com/0/100736/b718f234-2a19-5910-9b89-f31f4ee458f3.png)

## オブジェクトを紐付ける

今storyboard上のオブジェクトはコードに全く紐付いていない状態なので紐付けていきます。まず画面を以下の状態にします。左上のボタンの状態を同じにすればこのようにstoryboardとコード両方が見られるようになります。左側にはMain.storyboard、右側にはViewController.swiftを配置しています。
![スクリーンショット 2017-04-03 23.57.35.png](https://qiita-image-store.s3.amazonaws.com/0/100736/cc6b6797-ae3f-7eb9-7cdf-d54d77579362.png)

まずUILabelを紐付けます。controlを押しながらUILabelの真上からコードのviewDidLoadの上あたりに向かってドラッグします。すると以下の画面になります。
![スクリーンショット 2017-04-04 0.06.37.png](https://qiita-image-store.s3.amazonaws.com/0/100736/a01e8a4a-6437-07b7-9e2f-24f2968f59c9.png)
NameのところにtimerLabelと入れてconnectボタンをクリックします。すると以下のコードが生成されるはずです。
`@IBOutlet weak var timerLabel: UILabel!`
これで接続がされました。同じようにstartButton, stopButton, resetButtonも接続します。
![スクリーンショット 2017-04-04 0.11.31.png](https://qiita-image-store.s3.amazonaws.com/0/100736/69c84fa3-8c22-8647-7436-498b46ab719d.png)

## 必要な変数の準備

タイマーアプリを作るにあたって必要になる変数を準備します。時間をトリガーにしてイベントを発生させるTimerと時間の表示で使うFloatを用意しておきます。

```swift
private var timer = Timer()
private var count = 0.0
```

## タイマーをスタートする処理を書く

やっと具体的な処理を書く段階になりました。
まずは先程と同じようにstoryboardからコードファイルに向かってドラッグ&ドロップをします。
![スクリーンショット 2017-04-04 0.27.16.png](https://qiita-image-store.s3.amazonaws.com/0/100736/c620fcb8-dc6d-074e-9c08-2bb32dbe94c7.png)
動作を定義するので今度はただNameを入力するだけでなく、ConnectionをActionに変更する必要があります。ConnectionとNameをいじってconnectをクリックすると以下のコードが生成されるはずです。

```swift
@IBAction func startTimer(_ sender: Any) {
}
```

ではこのメソッド内にstartボタンをタップした時の処理を書きます。`isValid'を使うことによって今タイマーが動いているのかどうかがわかります。ということで動いていなかったらtimerにいろいろな設定を入れることにします。今回の場合は0.1秒ごとに繰り返しupdateTimerメソッドを呼んでカウントアップするようにします。よって以下のコードになります。

```swift
@IBAction func startTimer(_ sender: Any) {
    if !timer.isValid {
        timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(ViewController.updateTimer), userInfo: nil, repeats: true)
    }
}
```

ただこれをコピペしただけだと当然ながらまだupdateTimerメソッドを作成していないので怒られます。なのでupdateTimerメソッドを作成します。このメソッドは0.1秒ごとに呼ばれ、秒のカウントアップ表示を行います。よって以下のコードになります。

```swift
@objc private func updateTimer() {
    count += 0.1
    timerLabel.text = String(format: "%.1f", count)
}
```

`String(format: "%.1f", count)`の部分は「countを小数点第一位までのフォーマットにして文字列に直してくれている」というくらいの認識で良いです。

これによってカウントアップはできるようになりました。
![スクリーンショット 2017-04-04 1.09.45.png](https://qiita-image-store.s3.amazonaws.com/0/100736/9b8e4e0d-73b0-9d94-b75b-ff23747c02d5.png)

## タイマーをストップする処理を書く

スタートするときと同じようにstoryboardからコードに向かってドラッグ&ドロップします。今度はNameにstopTimerと入力しておきます。
![スクリーンショット 2017-04-04 9.23.35.png](https://qiita-image-store.s3.amazonaws.com/0/100736/c36848dd-940e-c5a4-d2dc-b28e811cef6c.png)

timerを止める処理なのでTimerクラスにあるinvalidateメソッドを使って止めます。よって以下のコードになります。

```swift
@IBAction func stopTimer(_ sender: Any) {
    if timer.isValid {
        timer.invalidate()
    }
}
```

## タイマーをリセットする処理を書く

最後にリセットしてまた0から始められるようにします。同じくstoryboardからコードに向かってドラッグ&ドロップします。NameはresetTimerにします。
処理としてはタイマーを止めること、タイマーの表示を0に戻すことを行えばよいです。なので以下のコードになります。

```swift
@IBAction func resetTimer(_ sender: Any) {
    timer.invalidate()
    count = 0.0
    timerLabel.text = String(format: "%.1f", count)
}
```

これで最低限の実装が入ったタイマーアプリの完成です。

# ソースコード

大したコードは書いていないですがこちらにあります。
https://github.com/akatsuki174/UILiveCoding

# 最後に

簡単なアプリならこのように意外とコードを書かずに作れます。なのでぜひiOSアプリ開発にチャレンジしてみてください。