症状:
- NSAttributedStringにNSParagraphStyleAttributeNameを利用してNSParagraphStyle経由でlineSpaceが付与されている。
- NSAttributedStringに複数の「区間」が存在する。例えばNSAttributedString全体が単一のAttributeによって構成されているときはこの問題は発生しません。2つ以上の異なるAttributeの区間が必要です。
- NSAttributedStringを描画するときに、横幅及び文字列の長さの都合で、1行で描画される。複数行になるときにはこの問題は発生しません。
- NSAttributedStringにNSBackgroundColorAttributeNameが付与されていない。または、NSBackgroundColorAttributeNameとNSKerningAttributeNameの両方が付与されている。
上記の条件を全て満たすとき、
本来、1行の文字列はレンダリングしたときに下端にlineSpaceが付与されてはいけませんが、この条件が満たされていると下端にlineSpaceが付与されてしまいます。先頭の画像の左上のケースがこの問題に相当します。
具体的な問題としては、
- 問題が発生するNSAttributedStringを使用したUILabel, UITextField, UITextViewの描画内容が思いっきり上にずれます(下に無駄なスペースが発生するので)
- NSAttributedStringの地点で壊れているので、Core Textを利用したり、
boundingRect(with size: CGSize, options: NSStringDrawingOptions = [], context: NSStringDrawingContext?) -> CGRect
を使っても一切回避できません
解決策:
この問題に対する正しいワークアラウンドの方法は一つしかありません。NSAttributedStringの全Attribute区間にNSBackgroundColorAttributeNameを付与し、かつどの区間にもNSKerningAttributeNameを付与しない。
背景色が不要の場合はUIColor.clearでも付与してごまかしてください。
以上です。よろしくお願いします。
参考:
- この問題の発端、一番わかり易い図説がある、誰も正しい回答を示せていない
- もう一つの例、カスタムフォントが悪いということにされているが、カスタムフォントは一切関係ない、システムフォントでも発生する
- 最後の例、この例によって「背景色があれば問題が発生しない」「カーニングを付与すると背景色があっても問題が再発する」ことが示され、この問題の正しい解決策が得られた