酢ろぐ!

カレーが嫌いなスマートフォンアプリプログラマのブログ。

Xcode 7.2(iOS 9.2 SDK)を使うとUILabelが崩れたりNSAttributedString#boundingRectWithSizeで意図しない値が返ってくる

時間ができた時にコツコツと Xcode 6.4 + iOS 8.4 SDKを使って開発していたアプリをXcode 7.2でビルドが通るようにしていました。要するにSwift 1.2からSwift 2.1.1への移行です。

ある時、UICollectionViewのフッターの表示が崩れていることに気付きました。細かい部分は実際のコードとは異なりますが概ね下記のような感じです。

// フッターに文字列を表示させる処理...

let font = UIFont.boldSystemFontOfSize(20)

let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
style.lineBreakMode = .ByCharWrapping
style.alignment = .Left
style.minimumLineHeight = font.leading + 2
style.maximumLineHeight = font.leading + 2

let attributes = [
    NSFontAttributeName: font,
    NSParagraphStyleAttributeName: style
]

titleLabel.attributedText = NSAttributedString(string: "ぴよぴよ", attributes: attributes)

↑ここでtitleLabelが潰れて表示されていました。

他にも同一事象だと思われることが幾つか発生していました。

  • UILabelで装飾付き文字列を設定した場合に表示が崩れている(UILabel#attributedText)
  • NSAttributedString#boundingRectWithSizeで明らかに小さすぎる高さが返ってくる

minimumLineHeightとmaximumLineHeightを指定している部分をコメントアウトしたところ、ラベルが潰れずに表示されたのでよかったよかったと思っていたのですが、本質的にはそこが原因ではありませんでした。

結論を書くと、Xcode 7.2(iOS 9.2 SDK)を使うとUIFont#leadingプロパティが0を返すようになっていたためです。

iOS 8.4とiOS 9.2のシミュレーターでUIFontのleadingプロパティの値をログで出すようにしてみました。

iOS 9.2 SDK + iOS 8.4で実行した場合

leading: 13.123 lineHight: 13.123
フッターのサイズ: (0.0, 0.0, 347.666, 273.968)

iOS 9.2 SDK + iOS 9.2で実行した場合

leading: 0.0 lineHight: 13.126953125
フッターのサイズ: (0.0, 0.0, 346.9437106269, 56.0)

UIFont#leadingプロパティが0で返ってきてしまい、この値を1行あたりの高さとして固定してしまっていた為、表示が崩れてしまっていました。

結論

UIFont#leadingプロパティではなくて、UIFont#lineHightプロパティを使わないといけません。

let style = NSParagraphStyle.defaultParagraphStyle().mutableCopy() as! NSMutableParagraphStyle
style.lineBreakMode = .ByCharWrapping
style.alignment = .Left
style.minimumLineHeight = font.lineHeight + 2
style.maximumLineHeight = font.lineHeight + 2

ドキュメントには以下のように書かれているだけでした。

f:id:ch3cooh393:20160118181233p:plain

leading Property
The receiver’s leading information. (read-only)

Use the lineHeight property instead.

iOS 9.0 SDKおよびiOS 9.1 SDKを使った場合でも同じような現象が発生するのかどうかは検証していません。

最初は、「Xcode 7.2(iOS 9.2 SDK)を使っている場合にNSParagraphStyle#minimumLineHeight、NSParagraphStyle#maximumLineHeightを指定すると表示が崩れてしまった」というタイトルでしたが途中で書き直しました。

以下、感想です。