読者です 読者をやめる 読者になる 読者になる

ObjecTips

基本Objective-Cで iOS とか OS X とか

UITableViewCell で Auto Layout + UITextView を使う際の Tips

iOS 8の self-sizing cell で自動で高さを調整してくれるように実装したところちょっと問題が。
まずセルのレイアウトは以下

f:id:Koze:20150629070221p:plain

上に UILabel, 下に UITextView を配置してラベルとテキストビューの間は0px
ラベルとテキストビューそれぞれのセルの contentView への margin をとって Auto Layout を設定する。
テーブルの表示内容として以下のように

    NSMutableArray *mArray = [NSMutableArray array];
    for (int i=0; i<indexPath.row; i++) {
        [mArray addObject:[NSString stringWithFormat:@"%d", i+1]];
    }
    cell.textView.text = [mArray componentsJoinedByString:@"\n"];

row の数だけ数字+改行を文字列として表示するようにした。

結果は以下

f:id:Koze:20150629071835p:plain f:id:Koze:20150629071841p:plain

テキストが入力されている箇所は問題ないが一番上のセルのテキストが空文字のケースでもテキストビューの高さが確保されている。
UILabel の場合はテキストが空文字であれば高さが無くなるので UILabel と UITextView ではちょっと挙動が異なるらしい。
UITextView をタップしてテキスト編集を始める事ができるUIの場合むしろこのように高さが確保される表示の方が良いし、テキスト編集をする必要が無い場合は UILabel を使えばいいのでこのデフォルトの挙動は理にかなっているが、今回はちょっと特殊な要求でタップして編集可能な UITextView を使いたいけど空文字の時は高さを無くして表示しないという挙動にしたいので UITextView のサブクラスを作って対応する。

いくらか試行錯誤して以下ような実装で簡潔に実現できた。

- (CGSize)intrinsicContentSize
{
    if (self.text.length == 0) {
        return CGSizeZero;
    }
    return [super intrinsicContentSize];
}

テキストが空文字か nil であれば CGSizeZero を返し、それ以外のケースではデフォルトの size を返す。

結果は以下

f:id:Koze:20150629072906p:plain f:id:Koze:20150629072912p:plain

まぁ特殊な用途ではあるけど intrinsicContentSize の活用の一例として。