[Xcode 8] layoutSubviewsのタイミングでビューのサイズが1000×1000になってしまう問題

2016.10.20

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

開発環境

  • Xcode Version 8.0 (8A218a)
  • Swift 3.0

何が起こったか

いつものようにstoryboardでUITableViewCellのレイアウトを組み、(もちろんAutoLayoutで)UIImageViewを円形にしたかったので以下のように実装したところUIImageViewが表示されなくて?となってしまいました。

レイアウトはこんな感じ

xcode8_1000_1000

コードはこんな感じ

override func layoutSubviews() {
    super.layoutSubviews()

    imageView.layer.cornerRadius = imageView.frame.width / 2
    imageView.layer.masksToBounds = true
}

これは何かおかしい...と思い、UIImageViewのframeを出力してみたところ、サイズが1000 x 1000になってる...

layoutSubviews imageView.frame = (0.0, 0.0, 1000.0, 1000.0)

対応方法

(当たり前ですが)drawrectの中ではframeがちゃんと意図した大きさになっていたので 以下のようにfunc draw(_ rect: CGRect)の中でframeを操作する処理を書くことで解決することができました。 stackoverflowの記事だとlayoutSubviewsの中でlayoutIfNeededを呼ぶことで解決できるような事が書いてありますが、workaround感が強いため、まだdrawrectの方がマシな気がします。

override func draw(_ rect: CGRect) {
    super.draw(rect)

    imageView.layer.cornerRadius = imageView.frame.width / 2
    imageView.layer.masksToBounds = true
}

ちなみにこの問題はXcode 7では起きません。 ひょっとしたら次のXcodeのバージョンでは直っているかもしれませんのでご注意ください。