iOS
Swift
Swift3.0

複数行に対応してUILabelのサイズに自動でフォントサイズを合わせる

adjustsFontSizeToFitっていう目的の機能のメソッドをextensionで付けました
タイトルはこう書いてますけど若干ダメです
とりあえず載せとけば誰かもっといい方法教えてくれそうなのであげます
あとadjustsFontSizeToFitWidthだと横は合うんですが高さではみだしたりしました

使い方

let lbl = UILabel()
lbl.backgroundColor = .blue //適当に色を付けてわかりやすくしてるだけ
lbl.textColor = .white
lbl.frame = CGRect(x: 0, y:0, width:100, height:20)
lbl.numberOfLines = 0//これ忘れがち
lbl.text = "うんこ\nうんこ\nうんこ\nうんこ\nうんこ\nうんこうんこうんこうんこうんこうんこうんこうんこうんこうんこうんこうんこ"

//拡張したメソッドを呼ぶ
lbl.adjustsFontSizeToFit()

extension

どんどんでかくしていってlabelよりでかくなれば終了っていう無限ループなバカっぽいやり方
そのためフォントサイズをでかくしていくstrideとmaxを決める必要がある
strideが小さくないと本当の意味ではぴったり合わない

UILabel+extension.swift
extension UILabel{
  func adjustsFontSizeToFit(_ stride:CGFloat = 1.0, _ max:CGFloat = 100) {
    var lblSize: CGSize
    var i:CGFloat = 0
    let maxSize = CGSize(width: 10000, height: 10000)
    while i < max {
      font = font.withSize(CGFloat(i))
      lblSize = self.sizeThatFits(maxSize)
      if lblSize.height > self.frame.height ||  lblSize.width > self.frame.width{
        break
      }
      i += stride
    }
    font = font.withSize(CGFloat(i-stride))
  }
}

補足

逆にフォントサイズにframeサイズを合わせるにはこんな感じ
複数行に対応させるには1回めちゃでかい幅にしとかないとダメらしい

//すごく大きな数
let w = 10000
lbl.frame = CGRect(x:0, y:0, width: w, height:lbl.frame.size.height)
lbl.sizeToFit()