StoryboardでTable Viewを使ってTwitterのTimelineっぽいUIを作る

## はじめに

この資料はスクーの`はじめてのiOSアプリ開発② - 基本操作を覚えよう`の[第4回 (はじめてのiOSアプリ開発 - Twitterのタイムラインのベースを作ろう（ライフサイクルイベント）)](https://schoo.jp/class/2713)でやった内容の写経です。

**授業を見てない人でもなるべく分かるように書いていきます。**

## 前提

数回の授業を通してTwitterなアプリケーションを作っていきます。

**前回までの授業で、UIを作るためのツールであるStoryboardの使い方の基本を学んでいます。**

## 今回やること

Twitterのタイムラインを表示させるベースを作ります。

![](https://i.gyazo.com/edb45f22eb38b18d6f38566590c99ecf.png)

こんなやつです。

* UITableViewを利用してツイートを表示
* ユーザーごとにアイコンを表示
* ツイート内容は名前と発言

## 1.  準備

それでは作っていきましょう。

いつもどおり、プロジェクトを立ち上げます。 `Create a new Xcode project`で新規プロジェクトを作成します。

![](https://i.gyazo.com/62642ceae0bc1a25f7bf946ed34924a0.png)

次に`Single View Application`を選択します。

![](https://i.gyazo.com/c6db71323063ea3672a5e618b588e083.png)

Product Nameに名前をいれてNextを押し、プロジェクトファイルの保存場所を決めて、Createをします。 Product Nameは任意の名前ですが、schoo_twitterとしました。
今回は使わ無いのでUse Core Dataのチェックは外しましょう。

![](https://i.gyazo.com/15ca54e4d63b132518be60ba20104b69.png)

こんな感じでプロジェクトの初期画面が表示されます。

![](https://i.gyazo.com/365893415e33cc9b78a8dea40f0883b9.png)

## 2. Storyboardでタイムライン部分を作る

左側のナビゲーションエリアで`Main.storyboard`を選択します。するとStoryboardが表示されます。

### Table View Controllerの追加
ここで右下のユーティリティエリアから`Table View Controller`をドラッグアンドドロップで追加しましょう。

>補足: Xcodeの画面の名前(ナビゲーションエリア、ユーティリティエリア)については[前の授業](https://schoo.jp/teacher/1335)でやりました。左のファイルがあるところ、右下のUIパーツがあるところ、とかで覚えてても問題無いと思います。

![](https://i.gyazo.com/6c336b338a15c2932c6d012084e1d0e2.gif)

### リスト表示を作ってみる

Storyboardの左側には`ドキュメントアウトライン`というものが表示されます。
UIパーツの階層構造を確認するためのものですが、ここで先ほど`Table View Controller`を追加しましたが、ドキュメントアウトラインには`Table View Controller Scene`という表示が追加されているはずです。 その中の`Table View Controller`の更に内部の`Table View`を選択します。

> ちょっと拡大した画像です。
![](https://i.gyazo.com/8127fc81a5117e43af825fda814dfdad.png)

この状態で右上(インスペクタエリア)のこのマーク![](https://i.gyazo.com/cc216cc80706746164aba5b9adf65c03.png)を選択すると、`Content`という項目のプルダウンメニューが`Dynamic Prototypes`になっていることが分かると思います。これを`Static Cells`に変更しましょう。

![](https://i.gyazo.com/cfa02ee7414333600d4792b75dbfde4e.gif)

`ドキュメントアウトライン`(左側メニュー)で`Table View`の下の階層に`Table View Section`という表示が追加されているはずです。`Table View Section`を選択してすると`ユーティリティエリア側`(画面右上)には`Rows`や`Header`、`Footer`という項目が表示されます。

* Rows: Rowsの値を変えると表示されるセルの行数が変動します。 
* Header: セルの上部にヘッダーテキストを設定できます。 
* Footer: セルの下部にフッターテキストを設定できます。

ちなみにここで`Header`の値を変えると`ドキュメントアウトライン`側の表記も変わります。(Headerをtimellineって書いたらドキュメントアウトライン側もtimelineに)
![](https://i.gyazo.com/d6514c3540e7ce5fcd906fec81bec748.gif)

### ラベルを追加してみよう

1行目のセルにラベルを二つ追加しましょう。右下からドラッグアンドドロップです。

![](https://i.gyazo.com/7e478b5408c5f4b1d2e15a0116fdede4.gif)

labelのテキストをダブルクリックで変更して、場所を調整します。
![](https://i.gyazo.com/75ae6ec90ce27adbb861b324364e5a65.gif)

### ラベル付きのリストを増やしてみる

`ドキュメントアウトライン`で先ほど変えたtimelineというパーツを選択し、 右上のインスペクタエリアで`Rows`を1まで減らした後に、増やしてみましょう。 1行目のセルには先ほどのラベル情報が入っていて、それがコピーされて2行目以降が追加されます。
![](https://i.gyazo.com/0be0a8e387690e0df45c3c3c545e9a16.gif)

### シュミレーターで確認

起動時のビューを切り替えます。 `View Controller`に向いてる`矢印`をここまでで作っていた`Table View Controller`側に移動させます。ドラッグアンドドロップで大丈夫です。
![](https://i.gyazo.com/ed2609b0d151f69284938f0207307065.gif)

ここまできたら、一度シュミレーターで確認します。
左上の三角ボタンをクリックします。 シュミレーターがちゃんと選択されているか確認しましょう。
> この画像の場合はiPhone6のシュミレーターになります。

![](https://i.gyazo.com/9f5018852ef3d89e8ae65f53c3497a30.png)

無事に起動するとこんな感じです。少し文字が重なっているけど気にし無い笑

![](https://i.gyazo.com/cd8981c87e176dcc61617f3b21cf0c2e.png)

ちゃんとリストが表示されましたね！

## 3. プログラムでリストを動的に書き換えてみよう

ここまでで、静的なリストを作りました。 次はプログラムで中身を変更する動的なリストを作ってみます。

ツイッター風なものに近づけます。

>途中からプロジェクト名がschoo_twitter2になっている画像もありますが気にしないでください。笑

### Table Viewを初期状態にしておきます。

* リストのタイプをDynamic Prototypesに戻します。
![](https://i.gyazo.com/a9dbe93cdc6d157dccc487c9016700a0.gif)

* セルの数を一つに戻して
![](https://i.gyazo.com/a2c83d93c787041bcf4b5155914d2bde.png)

* ラベルも削除しましょう。
![](https://i.gyazo.com/b66286acd79ca17eba71634255baee61.png)

### Table View CellのIdentifier設定

ドキュメントアウトラインのTable View Cellを選択した状態にすると、右上(インスペクタエリア)で`Identifier`という項目が設定できます。

![](https://i.gyazo.com/8fefe20cdfeb0bd5405e69ff85ed81bf.png)

`tweetCell`と入力しましょう。 
![](https://i.gyazo.com/a05b1c18c27cf6a46351795b430a4c66.png) 

ドキュメントアウトライン側の Table View Cellの名前が`tweetCell`に変わっていることを確認して下さい。
![](https://i.gyazo.com/522695dc9eaf376098013da57a34fa27.png)

### 画像を準備

冒頭で見せた、この画面のように、アイコンを表示させたいので画像を用意します。
![](https://i.gyazo.com/edb45f22eb38b18d6f38566590c99ecf.png)

二つの画像を用意しました。

![](https://i.gyazo.com/e6bbb94a6ab6f6dd2010f03f3e68e198.png) 

`images.xcassets`に画像を追加します。 画像を使うときはここに入れてあげるとプログラム中から呼び出せます。

![](https://i.gyazo.com/1f14ba4760553f41ff1cc3e90ba94f95.png)

`AppIcon`と表示されているエリアの下の`+ボタン`を押し、`New Image Set`を選択しましょう。 `Image`という項目が追加されますがリネームします。今回は`n0bisuke_icon`としました。

![](https://i.gyazo.com/16596c541b9eaeb1dbac025722fcf218.gif)

画像をドラッグアンドドロップします。

![](https://i.gyazo.com/5b8c1a9ba1230e5bb23103c3a46aeab8.gif)

もう一つの画像も同様に追加します。

![](https://i.gyazo.com/bf63f549a3167ea3cf9af18cdc7364ca.png)

### Table View側のswiftファイルを追加

ナビゲーションでプロジェクト名フォルダ部分で右クリックをすると出てくるメニューで`New File...`を選択しましょう。ファイルを追加出来るのでSwiftを選択してNextで次へ進めます。
![](https://i.gyazo.com/a64b370fda358c342e13e5d94ef030ab.gif)

名前は`TimelineViewController.swift`にします。
![](https://i.gyazo.com/819b005a8d710ac8a14fb2e93f6048f8.png)

こんな感じで`TimelineViewController.swift`が追加されます。
![](https://i.gyazo.com/1d521499e60997c579c7d6842a756227.png)

### プログラムを記述(コピペ)

`TimelineViewController.swift`に以下のコードをコピペで上書きします。

```TimelineViewController.swift
import UIKit

class TimelineViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
    
    let cellIdentifier = "tweetCell"
    var tweets:[Dictionary<String, AnyObject>]?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Uncomment the following line to preserve selection between presentations
        // self.clearsSelectionOnViewWillAppear = false
        
        // Uncomment the following line to display an Edit button in the navigation bar for this view controller.
        // self.navigationItem.rightBarButtonItem = self.editButtonItem()
        
        tweets = [
            ["name": "n0bisuke", "description": "My name is n0bisuke", "icon":"n0bisuke_icon"],
            ["name": "nagamine", "description": "My name is nagamine", "icon":"web_chiro_icon"],
            ["name": "n0bisuke", "description": "My name is n0bisuke", "icon":"n0bisuke_icon"],
            ["name": "nagamine", "description": "My name is nagamine", "icon":"web_chiro_icon"],
            ["name": "n0bisuke", "description": "My name is n0bisuke", "icon":"n0bisuke_icon"],
            ["name": "nagamine", "description": "My name is nagamine", "icon":"web_chiro_icon"]
        ]
        
        //        var tweetCell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellIdentifier)
        //        tableView.registerClass(tweetCell.dynamicType, forCellReuseIdentifier: cellIdentifier)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // MARK: - Table view data source
    
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        // #warning Potentially incomplete method implementation.
        // Return the number of sections.
        return 1
    }
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete method implementation.
        // Return the number of rows in the section.
        
        if let tweetsList = tweets {
            return tweetsList.count
        }
        
        return 0
    }
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        var aCell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as? UITableViewCell
        
        // Configure the cell...
        if aCell == nil {
            aCell = UITableViewCell(style: .Subtitle, reuseIdentifier: cellIdentifier)
        }
        
        var cell = aCell!
        cell.imageView?.image = UIImage(named: (tweets![indexPath.row]["icon"] as? String)!)
        cell.textLabel?.text = tweets![indexPath.row]["description"] as? String
        cell.detailTextLabel?.text = tweets![indexPath.row]["name"] as? String
        
        return cell
    }
    
    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        self.performSegueWithIdentifier("showTweetDetailViewController", sender: nil)
    }
    
    override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 50.0
    }
    
}
```


`let cellIdentifier = "tweetCell"`の部分と
`tweets = []`内のiconの値の部分はここまでで指定してきた`Identifier`と`Image Set`の名前です。

>細かいプログラム解説は省略

### Storyboardとswiftファイルの紐付け

今作成した`TimelineViewController.swift`はまだStoryboard側とは紐付いてません。

ドキュメントアウトラインでTable View Controllerを選択し、インスペクタエリアで隣の![](https://i.gyazo.com/37a11e44b6f5d15612950a29762fdbee.png)アイコンを選択します。

![](https://i.gyazo.com/98e5ee6bb0517bb6cc0d62961a5ca755.png)

Classの部分に`TimelineViewController`と入力してエンターで確定させましょう。これで追加したSwiftファイルとTable View Controllerが紐付きました。

![](https://i.gyazo.com/f5d70ea0f56d54750ad1991911bac1de.png)

### 完成！シュミレーターを起動してみる

ここまでの手順で問題無ければ、シュミレーターを実行すると以下のようなテーブルビューが表示されます。

![](https://i.gyazo.com/d92fd2bb5971ff2c21617e25d8f3e8af.png)

お疲れ様でした。

## まとめ

以下を行いました。

* Storyboardの使い方としてTable Viewについて
* Table ViewのStatic(静的)設置の仕方
* Table ViewにプログラムからDynamic(動的)設置の仕方