💈

[iOS]ヘアラインビューの実装

2023/05/22に公開

iOSのアプリ開発では、1pxの細い線を度々引くことがあります。

解説記事によって揺らぎがあるので、この記事での定義を説明すると1pxとは画面ピクセルを1つ取ったサイズということです。
つまり、通常Autolayoutなどで扱う数値に画面スケールを割ったもの。

let _1px = 1.0 / scale

このように髪の毛のように細い線をヘアラインなどと呼んだりしますが、iOSではどうやって作れば良いのでしょうか。
よくある実装としては次のようなもの

let height = 1.0 / UIScreen.main.scale
hairlineView.frame.size.height = height

しかし、UIScreen.mainはiOS16でdeprecatedになってしまいました。

そこで、

guard let window = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
let height = 1.0 / window.screen.scale

と、ついついscreenのscaleを取りに行ってしまいますがもっと良い方法があります。
それが、traitCollectionのdisplayScale。

let height = 1.0 / traitCollection.displayScale

特にiPadなど、画面に接続した際はdisplayScaleは@3xに固定されるとは限りません。
traitCollectionを使うことで、traitCollectionDidChange(_:)で変更を検知することも容易になり安全に扱うことができます。

public override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  let height = 1.0 / traitCollection.displayScale
}

また、SwiftUIでも同様のEnvironmentが存在します。

@Environment(\.displayScale)
var displayScale: CGFloat

こちらも変更検知が自動で出来るので、おすすめです。

Discussion