LoginSignup
18
16

More than 5 years have passed since last update.

safeAreaLayoutGuideをiOS 10で使う(?)

Last updated at Posted at 2017-11-01

もちろんできません

safeAreaLayoutGuideはiOS 11+のみで使えるので、iOS 10等をサポートしているとエラーになります。

大抵の場合は、画面端からの代わりにsafeAreaを使って、iPhone Xでもレイアウト崩れないようにしたいと思います。

とはいえ、レイアウトごとに

if #available(iOS 11.0, *) {
    view.safeAreaLayoutGuide.leftAnchor
} else {
    view.leftAnchor
}

みたいにするのは冗長です。

これを同じように扱えればよいわけです。

第一案

結果

UIViewのAnchorを、UILayoutGuideとして取り出すことで対応しました。

let safeAreaLayoutGuide = view.safeLayoutGuideOrSelfLayoutGuide()

これでiOS 11以上ならsafeAreaLayoutGuideが、iOS 10以下では自分自身のLayoutGuideが返されます。

実装

まず、leftAnchorなどはUIViewのプロパティなので、ProxyするクラスをUILayoutGuideを継承して作ります

private final class UIViewLayoutGuideProxy: UILayoutGuide {

    private unowned var _base: UIView

    override var leftAnchor: NSLayoutXAxisAnchor {
        return _base.leftAnchor
    }

}

そして、このiOS 10以下ではこのProxyを返すようなメソッドを生やせば完了です。

extension UIView {
    func safeLayoutGuideOrSelfLayoutGuide() -> UILayoutGuide {
        if #available(iOS 11.0, *) {
            return self.safeAreaLayoutGuide
        } else {
            return UIViewLayoutGuideProxy(self)
        }
    }
}

Gist

以下でソースを公開しています(案1の方)

第二案

extension UIView {
    var safeLeftAnchor: NSLayoutXAxisAnchor {
        if #available(iOS 11.0, *) {
            return self.safeAreaLayoutGuide
        } else {
            return self.leftAnchor
        }
    }
}

みたいなのも考えましたが、せっかく .leftAnchor の名前はUIViewでもUILayoutGuideでも揃っているので、崩したくないなと思いました。
が、以下のようにviewがdeinitされた後に呼ばれる可能性がなくなるので、こっちのほうがいいかもしれません、、、(今更)

let tmp = view.safeLayoutGuideOrSelfLayoutGuide()
// viewがdeinitされた後に呼ぶと_baseがnilで落ちる
print(tmp.leftAnchor)

案2として同じGistの下側にあります!

第三案

Rxみたいにしてみた。これが一番いいかも

view.safeAreaLayoutGuideCompatible.leftAnchor

という感じ

18
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
16