プログラミング教室で Swift での TODO アプリの作り方を説明しました. その2

[その1の記事](http://qiita.com/mironal/items/bb0ab5c42fe687b301ec)

---

## 概要

プログラミング教室で Swift で iOS のアプリを作る授業を行いました。

環境、生徒のスペック、授業の始め方などは [その1の記事](http://qiita.com/mironal/items/bb0ab5c42fe687b301ec) を参照してください。

## やったこと

今回の授業では

- Swift の基本的な文法
- 前回作った TODO アプリの続き

を行いました。

前回はとりあえず動くものを作り、 Xcode や Swift の雰囲気を感じ取ってもらうことを主としました。

今回は前回書いたもののそれぞれの意味がわかるように基本的な文法を説明した後にそれを踏まえて前回の続きを行いました。

いきなり文法の授業をやるとつまらないと思ったのでこのような段取りにしました。

### 作るもの

Swift の基本的な文法では Xcode の Playground の機能を使った変数宣言から class, struct の宣言方法、 Optional の概要、関数宣言などを説明しました。

TODO アプリの方はタスクを追加するボタンを押したらダイアログが出てそこにタスクを書いて `OK` を押したら TableView に項目が追加される機能を作りました。

![Simulator_Screen_Shot_2016_06_26_11_42_55.png](https://qiita-image-store.s3.amazonaws.com/0/17704/cef60d66-3f35-c357-27d8-954df951721a.png)


## 進め方(1.5時間)

### Swift の基本的な文法

まずは PlayGround で Swift の文法を説明しました.

変数宣言のあとに突然クラス宣言の説明になっているのは生徒さんから「let としてインスタンス化したオブジェクトのプロパティーは変更できなくて、 var の場合は変更できるの？」という鋭い質問が飛んだためです。

クラスを定義する際に let としてあれば変更できないし、 var であれば変更できることを説明するために実際にクラスを作ってその時の動作の違いについて説明しました。

生徒さんの中に既に Haskell をやったことがある方がいて Option がどういうものなのかをすぐに理解してもらえていろいろな意味で衝撃的でした。

```swift
//: Playground - noun: a place where people can play

import UIKit

import XCPlayground

/*
let frame = CGRect(x: 0, y: 0, width: 150, height: 150)

let view = UIView(frame: frame)

view.backgroundColor = UIColor.purpleColor()

XCPlaygroundPage.currentPage.liveView = view

*/

let hoge = 1
var huga = 2

// hoge = 2 // 代入できない
huga = 1 // 代入できる

// クラスの書き方
class Dog {
    let name: String
    var age: Int
    init(name: String) {
        self.name = name
        age = 0
    }

    func sayName() {
        print(name)
    }
}

let dog = Dog(name: "poti")

dog.age = 20 // 代入できる
// dog.name = "aa" // 代入できない
// 構造体 (定数しか無い場合はオススメ)
struct Cat {
    let name: String
    let age: Int
}

let cat = Cat(name: "neko", age: 20)

// 型(クラス)

let a: Double  = 1.1
// a の型を省略した書き方(型推論)
let b = 1.1

let s = "aaaa"
let ss: String = "aaaa"

let name = "obama"

// Hello obama !
let string = "Hello \(name) !"

// if 文

let value = 10

if value < 2 {

} else if value < 10 {

} else {

}

// 配列, 辞書

// let array = [1,2,3,4]
let array: [Int] = [1,2,3,4]

// let dict = ["key": "value", "key1": "value1"]
let dict: [String: String] = ["key": "value", "key1": "value1"]

// for

for i in array {
    print(i)
}

// ベタに書く
array.forEach { (i: Int) in
    print(i)
}

// 型を省略
array.forEach { i in
    print(i)
}

// ブロックの引数を省略
array.forEach {
    print($0)
}

// オプショナル型, 値があるかどうかを表す
// 文字列があるかもしれないし、無いかもしれない
let option: String? = "aa"
let option1: Int? = 2

// オプショナル型じゃないと nil が入らない
// = 必ず値がある
// let notOpt: String = nil

if let opt = option,
    opt1 = option1 {
    print(opt)
} else {
    print("値が nil")
}

// 関数宣言

// func 関数名(引数のリスト) -> 戻り値の型
func add(a: Int, b: Int) -> Int {
    return a + b
}

// 戻り値の型が void の関数
func aa() {

}

// プロトコル
// プロトコル指向プログラミング <- Swift はこっち派
// オブジェクト指向プログラミング <- Java とか
```

### TODO アプリ

先ほどスクリーンショットで示した機能を追加しています。

やったこととしては `pushAddButton` のメソッド内を変更しただけです。

今回書いたコード量は少ないですが

- アラートの表示の仕方
- ブロックの書き方
- if let での値の束縛
- プレースホルダーを使うことによる UX の向上
- TableView の更新

などなど、密度の濃いコードになっています。

先ほどの Swift の文法で説明したことがどんどん出てくるので理解が深まったと思います。

```swift
//
//  ViewController.swift
//  TODO
//
//  Created by mironal on 2016/06/11.
//  Copyright © 2016年 covelline. All rights reserved.
//

import UIKit

class ViewController: UITableViewController {

    var items = ["item 1", "item 2", "item 3"]

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return items.count
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)

        cell.textLabel?.text = items[indexPath.row]

        return cell
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")

        // + ボタンと `pushAddButton:` メソッドのひも付け
        navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .Add,
                                                            target: self,
                                                            action: #selector(ViewController.pushAddButton(_:)))
    }


    // + ボタンが押された時に実行されるメソッド
    func pushAddButton(sender: UIBarButtonItem) {

        // アラートのダイアログを作る
        let alert = UIAlertController(title: "タスクを追加", message: nil, preferredStyle: .Alert)

        // テキスト入力欄を追加
        alert.addTextFieldWithConfigurationHandler { textField in
            // プレースホルダー
            textField.placeholder = "タスク名を追加"
        }

        // OK ボタンを追加(自分で追加してみよう)
        alert.addAction(UIAlertAction(title: "OK", style: .Default, handler: { action in
            // OK おされたときの処理

            if let text = alert.textFields?.first?.text {
                // tableView に追加する処理
                
                self.items.append(text)
                self.tableView.reloadData()
            }
        }))
            
        // キャンセルボタンを追加
        alert.addAction(UIAlertAction(title: "Cancel", style: .Cancel, handler: nil))

        // アラートを表示する
        presentViewController(alert, animated: true, completion: nil)
    }

    // 削除する奴
    override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {

        // delete を押したところの場所
        let index = indexPath.row

        tableView.beginUpdates()

        items.removeAtIndex(index)
        let indexPaths = NSIndexPath(forRow: indexPath.row, inSection: indexPath.section)
        tableView.deleteRowsAtIndexPaths([indexPaths], withRowAnimation: .Automatic)

        tableView.endUpdates()
    }

}

```

## まとめ

プログラミング教室で高校生に向けて Swift での iOS アプリの作り方についての授業を行いました。

内容は以下の２つです。

1. Swift の基本的な文法
1. 前回作った TODO アプリの機能追加

Haskell をやっていた生徒さんは理解力・質問の内容ともに非常にハイレベルでした。

そのため、この生徒さんが興味を示した部分に関しては深いところまで説明を行いました。

やっている事自体は簡単なことだったので他の生徒さんもなんとなくの理解はできたと思います(と願っています)。

また近いうちに次回を開催したいと思います。

## 授業風景

![IMG_8568.jpg](https://qiita-image-store.s3.amazonaws.com/0/17704/75d1d45e-c952-3e63-f8c0-8af6e3152312.jpeg)

![IMG_8569.jpg](https://qiita-image-store.s3.amazonaws.com/0/17704/772762ed-3c3d-0186-bac3-ab7c76de3ba8.jpeg)


## 開催場所

[TENTO さいたま](http://www.tento-net.com/school/tento-saitama)