スタータープロジェクト
スタータープロジェクトでは、テーブルビューのセルに UITextView
が一つだけあり、それには次のようなビューの制約(レイアウト)が含まれています:
このプログラムビュー Storyboard
では、テキストが表示されるはずです。
しかしプログラムを実行しても画面には何も表示されません。テーブルビューのセルの高さが0になっているようです。
この記事ではこの問題の修正の仕方について学んでいきます。
問題を修正する
スクロールを無効化する
デフォルトでは UITextView
はスクロールが有効になっています。固定した高さにするためにそれを無効化する必要があります。
もともと、次のようなテーブルビューのクラスコードになっています。
class demoCell: UITableViewCell {
@IBOutlet weak var textField: UITextView!
}
このコードを次のように更新します。
class demoCell: UITableViewCell {
@IBOutlet weak var textField: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
textField.isScrollEnabled = false
}
}
再びシミュレーターでプログラムを実行すれば、UITextView
のコンテンツが正常に表示されているのがわかります。
テキストの内容が変更された時にビューの高さを更新する。
UITextView
]内のテキストを編集しようとしても、テーブルビューのセルの高さは変わりません。しかし、高さは動的に変更する必要があります。
自動で高さを設定する
テーブルビューのセルの高さを自動的に設定するようにシステムに指示することができます。
tableView.rowHeight = UITableView.automaticDimension
テキストの編集と連動させる
UITextViewDelegate
を設定して、テキストが変更されたときにイベントが連動するようにします
class demoCell: UITableViewCell, UITextViewDelegate {
@IBOutlet weak var textField: UITextView!
override func awakeFromNib() {
super.awakeFromNib()
textField.isScrollEnabled = false
textField.delegate = self
}
func textViewDidChange(_ textView: UITextView) {
//新しいテキスト
}
}
テキスト編集をテーブルビューコントローラに報告する
この変更を UITableViewController
に報告すると、UITableViewController
がテーブルビューをリフレッシュしてセルの高さが更新されます。
プロトコルを作成する
protocol demoCellDelegate : AnyObject {
func textDidChange()
}
テーブルビューのセルで、demoCellDelegate.textDidChange()
の関数を呼び出します
class demoCell: UITableViewCell, UITextViewDelegate {
@IBOutlet weak var textField: UITextView!
weak var delegate: demoCellDelegate?
override func awakeFromNib() {
super.awakeFromNib()
textField.isScrollEnabled = false
textField.delegate = self
}
func textViewDidChange(_ textView: UITextView) {
//新しいテキスト
delegate?.textDidChange()
}
}
そして、テーブルビューのクラスで、デリゲートを設定します:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "demo") as! demoCell
cell.textField.text = "テスト テスト テスト テスト テスト テスト テスト テスト テスト テスト テスト"
cell.delegate = self
return cell
}
extension ViewController: demoCellDelegate {
func textDidChange() {
//TODO
}
}
テーブルをリロードせずにテーブルビューを更新する
ここで、テーブルの高さを更新するために、reloadData()
を使用しないでください。代わりに tableView.beginUpdates()
と tableView.endUpdates()
を使用してください。
extension ViewController: demoCellDelegate {
func textDidChange() {
tableView.beginUpdates()
tableView.endUpdates()
}
}
そして、このプログラムをシミュレータで再度実行すると、次のようになります。