しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

Storyboard+UIScrollView+AutoLayoutでhas ambiguous scrollable contentエラーが出ないようにする

Storyboard上でUIScrollView+AutoLayoutを使うと下のようなエラーが出る事があります。
今回はその対処法を調べました。
Xcodeのバージョンは13です。

f:id:llcc:20211212193115p:plain

参考にしたのは下URLです。

qiita.com

まずはプロジェクトを作ってMain.storyboardにUIScrollViewを配置します。
今回はUIScrollViewを縦にだけスクロールするようにしようと思います。

f:id:llcc:20211212193023p:plain

配置したらUIScrollViewに下のような制約を追加します。

f:id:llcc:20211212193424p:plain

制約を追加すると下のようにエラーになり線が赤くなります。

f:id:llcc:20211212193231p:plain

エラー対策の為、まずはUIViewをUIScrollViewの直下に配置します。

f:id:llcc:20211212193342p:plain

次に左側のメニューでViewとContent Layout Guideを選びます。

f:id:llcc:20211212222511p:plain

この状態で下のような制約を追加します。

f:id:llcc:20211212222609p:plain

続けてViewにHeightの制約を追加します。

f:id:llcc:20211212222653p:plain

これでyやheightに関するエラーは消えました。

f:id:llcc:20211212222723p:plain

次はxとwidthに関するエラーの対応をします。
今度はViewとFrame Layout Guideを選びます。

f:id:llcc:20211212222806p:plain

この状態でEqual Widthsの制約を追加します。

f:id:llcc:20211212222840p:plain

これでエラーが消えました。
実行するとスクロールのContentHeightが1000になっている事がわかります。

f:id:llcc:20211212222906p:plain

先程出てきたContent Layout GuideとFrame Layout Guideですが公式サイトに説明がありました。

https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide

https://developer.apple.com/documentation/uikit/uiscrollview/2865772-framelayoutguide

公式サイトの説明は下の通りです。
要するにContent Layout GuideはUIScrollViewのcontentSizeに関するガイドでFrame Layout GuideはUIScrollViewのframeに関するガイドです。
そのためFrame Layout GuideとViewにEqualWidthsを付ければcontentSize.widthがUIScrollViewのframe.widthと等しくなったのだと思われます。

■ Content Layout Guide
Use this layout guide when you want to create Auto Layout constraints related to the content area of a scroll view.
■ Frame Layout Guide
Use this layout guide when you want to create Auto Layout constraints that explicitly involve the frame rectangle of the scroll view itself, as opposed to its content rectangle.

続けてContentHeightを動的に変える方法についても見ていきます。
まずはViewControllerにNSLayoutConstraintのIBOutletを作ります。

class ViewController: UIViewController {
    @IBOutlet var constraint: NSLayoutConstraint!
}

Storyboardから今作ったIBOutletとHeightに関するNSLayoutConstraintを紐付けます。

f:id:llcc:20211212223118p:plain

あとはNSLayoutConstraintの値を変えればContentHeightの値が変わります。

class ViewController: UIViewController {
    @IBOutlet var constraint: NSLayoutConstraint!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        constraint.constant = 2000
    }
}