2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

UITableViewのdataSourceって結局なに?

Posted at

はじめに

swiftを学び始めた人が一番最初につまづくのがtableViewである、と僕は思っています。
その難しい要因を生み出しているものの一つがこれ。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        
}
    
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
}

そう。こいつら。

実はこれらについて理解するには、delegateという概念を知っていなければなりません。

delegateとは何か

delegate、和訳すれば「委任する」とかなる言葉ですが、ではプログラムを委任するとはなんなのか。
さきほどのtableViewのコードを参考に考えてみましょう。

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 1
}

このコードではtableViewのセルの数が1つになりますね。
重要なのは、このコードがViewControllerのコードの中に書かれていること。よくよく考えてみれば、tableViewに対して直接設定をしなくても設定がうまくいっていますよね。

これこそ、tableViewの設定コードをViewControllerに委任しているということなわけです。

ここで、ViewControllerに処理を委任するよ、ということを、ViewControllerに知らせなくてはなりませんね。

tableView.dataSource = self

これを書き忘れたことでコードがあっているのにtableViewに何も表示されないという経験をしたことがある人、結構いると思います。

ちなみに、tableViewにはdelegateというプロパティもありますよね。名前通りで、これもdelegateです

実際にdelegateを作ってみよう

ここまでの説明でなーんとなくdelegateという存在が何者なのかわかったと思います。
そこで、実際に作ってみてより理解を深めてみましょう!

今回は、ボタンを押したら表示されている数が1増えるという基本的なアプリを、delegateを用いて作ってみようと思います。

delegateを用いない場合

さきにどんなものを作るのかのイメージです。

class ViewController: UIViewController {
    @IBOutlet var label: UILabel!

    var num: Int = 0

    override func viewDidLoad() {
    }

    @IBAction func buttonPressed() {
        num += 1
        label.text = String(num)
    }
}

どこにdelegateを用いるか

さて、その上でどんなふうにdelegateを用いるかですが、先ほど出したtableViewのように、画面のパーツをdelegateを用いて実装してみたいと思います。
今回は数字を表示するlabelをdelegateを用いて実装してみましょう!

delegateを用いた実装

まず、delegateを用いるので、わかりやすく区別するために新しいlabel(CustomLabel)を作ってみましょう

class CustomLabel: UILabel {
}

そして、次に書くprotocolというものがdelegateの大本命となります。

protocol CustomLabelDelegate {
}

これでdelegateの外枠が作れました。

次に、CustomLabelとDelegateを接続します

class CustomLabel: UILabel {
    var delegate: CustomLabelDelegate? = nil

    func reloadData() {
        if let delegate {
            self.text = delegate.labelText()
        }
    }
}

protocol CustomLabelDelegate {
    func labelText() -> String
}

これで、CustomLabelがdelegateプロパティを持ちましたね。
このdelegateが設定されている、つまりnilでないなら、reloadData()が呼び出された際に処理が行われる、という感じになっています。

加えて、protocolにfunc setText() -> Stringとありますね。中身のない関数のような書き方がされていますが、これによって「こんな関数がありますよ、でもその内容は誰かに委託しますよ」ということが宣言できていることになっています。

さて、これらを用いて、ViewControllerのコードを書きましょう。

class ViewController: UIViewController, CustomLabelDelegate {
    @IBOutlet var label: CustomLabel!
    
    var num: Int = 0
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        label.delegate = self
    }

    @IBAction func buttonPressed() {
        num += 1
        
        label.reloadData()
    }

    func labelText() -> String {
        return String(num)
    }
}

こんな感じになります。

まとめ

流れをおさらいしましょう。

1. protocolでdelegateを作成
2. classにdelegateを持たせる
3. viewControllerにdelegateの先を設定し、viewController内でprotocolの関数を定義
4. viewController内からclassのdelegateに関連のあるメソッドを呼び出す

あまり自分から進んで用いることは多いようには思いませんが、使えるくらいに理解しておくことでTableViewへの理解がぐっと上がります!この記事が参考になると嬉しいです。

おまけ

delegateのところでこんな書き方をしていました。

if let delegate {
    ...
}

これは以下と同じ意味合いです。

if let delegate = delegate {
    ...
}

この書き方好き。

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?