Help us understand the problem. What is going on with this article?

SwiftでTableViewCellの高さを動的に変える

More than 3 years have passed since last update.

はじめに

題名の通り、TableViewCellの高さを動的に変えてみます。
Self-Sizing Cellsとかいうやつです。

本記事のサンプルは、Xcode Ver7.3.1で実装しました。
iOS 8.0以降対象です。

Self-Sizing Cells??

セルの高さを自力で計算することなく動的な高さを持つセルを定義できるものです。

完成イメージ

name, commentを持つJSONからデータを取得します。
サンプルなので、表示する文字列はテキトーです。

profileSample.json
{
    "profile": [
                {"name": "AAA", "comment": "abcd123"},
                {"name": "BBB", "comment": "あいう\nえお"},
                {"name": "CCC", "comment": "こめんと\nコメント\nComment"},
                {"name": "DDD", "comment": "01234\n56789\n98765\n43210"},
                {"name": "EEE", "comment": "コメント\nコメント\nコメントコメント\nコメコメントントコメントコメント\nabc123"},
                {"name": "FFF", "comment": ""},
                {"name": "GGG", "comment": "abcd123"},
                {"name": "HHH", "comment": "あいう\nえお"},
                {"name": "III", "comment": "こめんと\nコメント\nComment"},
                {"name": "JJJ", "comment": "01234\n56789\n98765\n43210"},
                {"name": "KKK", "comment": "コメント\nコメント\nコメントコメント\nコメコメントントコメントコメント\nabc123"},
                {"name": "LLL", "comment": ""},
                {"name": "MMM", "comment": "コメント\nコメント\nコメント\nコメント\nコメント\nコメント"},
                {"name": "NNN", "comment": "apple\niOS"},
                {"name": "OOO", "comment": ""},
                {"name": "PPP", "comment": "0\n11\n222\n3333\n44444\n555555\n6666666\n77777777\n888888888\n9999999999"},
                ]
}

このデータから、
名前(赤字)とコメント(黒字、複数行)を持つTableViewCellを作ります。
Simulator Screen Shot 2016.09.13 1.44.36.png

Cell内に配置したパーツに適切な制約をつける

本サンプルでは、Cell内にnameLabelとcommentLabelの二つ配置しています。
それぞれのラベルに適切な制約をつけてあげます。

nameLabelは、
上左右 Constrain 0
下 Constrain 8としました。

commentLabelは、
下左右 Constrain 0
上 Constrain 8としました。

(単に上下左右に制約をつけただけです。)

スクリーンショット 2016-09-13 1.58.54.png

また、commentLabelは複数行のテキストを表示するので
Linesに0を設定しておきます。
スクリーンショット 2016-09-17 21.03.07.png

TableViewの設定

estimatedRowHeightを設定する

tableView.estimatedRowHeight = 66
セルの高さを計算する直前までの高さになります。
(デフォルトの高さというイメージですかね。)

rowHeightにUITableViewAutomaticDimensionを設定する
tableView.rowHeight = UITableViewAutomaticDimension

estimatedRowHeightに任意の値を設定し、
rowHeightにUITableViewAutomaticDimensionを設定することで
動的にセルの高さを設定してくれるようになります。

その他の部分は、基本的なTableViewの実装と変わりません。
セルに表示するデータを取得したり、UITableViewDataSourceのデリゲートメソッドを定義したりするだけです。(基本的なTableViewの実装部分については説明を割愛させていただきます。)

作成したコード

ProfileViewController.swift
import UIKit

struct ProfileModel {
    var name = ""
    var comment = ""
}

struct ProfilesModel {
    var profiles = [ProfileModel]()
}

class ProfileViewController: UIViewController {

    @IBOutlet weak var tableView: UITableView!
    var profilesModel = ProfilesModel()


// MARK: Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.estimatedRowHeight = 66
        tableView.rowHeight = UITableViewAutomaticDimension

        guard let jsonFilePath = NSBundle.mainBundle().pathForResource("profileSample", ofType: "json") else {
            return
        }
        // JSONファイルのデータ整形し、profilesModelにセットする
        JsonParser.parse(&profilesModel, jsonFilePath: jsonFilePath)


        tableView.dataSource = self
    }
}


// MARK: UITableViewDataSource
extension ProfileViewController: UITableViewDataSource {
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return profilesModel.profiles.count
    }

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

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ProfileCell
        cell.nameLabel.text = profilesModel.profiles[indexPath.row].name
        cell.commentLabel.text = profilesModel.profiles[indexPath.row].comment
        return cell
    }
}
ProfileCell.swift
import UIKit

class ProfileCell: UITableViewCell {
    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var commentLabel: UILabel!


    override func awakeFromNib() {
        super.awakeFromNib()
        nameLabel.textColor = UIColor.redColor()
    }
}

JSONのparseしているのは、こちら。

JsonParser.swift
import UIKit

class JsonParser: NSObject {
    /// JSONをparseする
    class func parse(inout profilesModel: ProfilesModel, jsonFilePath: String) {
        guard let data = NSData(contentsOfFile: jsonFilePath) else {
            return
        }

        let dictionary:NSDictionary = try!
            NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as! NSDictionary

        var profileModel = ProfileModel()

        let profiles = dictionary["profile"] as! Array<NSDictionary>
        for profile in profiles {
            profileModel.name = profile["name"] as! String
            profileModel.comment = profile["comment"] as! String

            profilesModel.profiles.append(profileModel)
        }

    }
}

さいごに

TableViewCellの高さを動的に変えるのって大変なのかなーと思っていたけれど
ちゃんと整理してみたらとても簡単にできました。

y-okudera
ぼのぼの。 アカウント名をGitHubに合わせました!(旧アカウント名: @okuderap)
andfactory
Smartphone Idea Companyとして、人々の生活に「&(アンド)」を届ける。
https://andfactory.co.jp/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away