LoginSignup
1
1

More than 3 years have passed since last update.

AutoLayoutのViewに自作Viewを参照して描画する際、レイアウトが端末によって崩れる問題の解決方法

Last updated at Posted at 2020-08-04

発生している問題点

AutoLayoutで配置せずにコードで自作したView
AutoLayoutを使用して配置したViewの位置を参照して描画する際,アプリを実行した時にレイアウトが崩れる問題

具体的に言うとAutoLayoutで配置しているスライダーの位置を取得してそれの割合で自作のViewを描画するプログラムを書いた時に発生した問題

StoryBoardで設定しているiPhone11では正常に描画

Main_storyboard__Edited.png

Simulator→iPhone8でレイアウトが崩れる

なぜ起きたか?

結論→View描画のライフサイクル を理解していなかった。

  • スライダーMaxPointを取得する際に現在設定しているのStoryBoardのポイントを取得

以下のコードは自作Viewを作成する際に使用したコード
イニシャライザにスライダーの最小値と最大値を渡している

class MakeViewFactory{
init(slidermaxVal:Float,sliderminPoint:CGPoint,slidermaxPoint:CGPoint,width:CGFloat,height:CGFloat) {
        self.sliderMaxValue = slidermaxVal
        self.sliderMinPoint = sliderminPoint
        self.sliderMaxPoint = slidermaxPoint
        print(slidermaxPoint)
     //スライダーの最大値を出力
        self.width          = width
        self.height         = height

    }
・・・中略・・・
}

ここに値を渡すタイミングが悪かった...

機種別のスライダーの CGPoint

  • iPhone11 (394.0, 383.0)
  • iPhone8 (355.0, 278.5)

print(slidermaxPoint)でデバックしてみると、

//StoryBoardでiPhone11を設定
(394.0, 383.0)

//この値で描画が行われている
//ここで何が行われているかが鍵

//ViewDidLoad()実行後→iPhone8にSliderViewが変更
(355.0, 278.5)

変更される前にスライダーに値を渡していた。

解決策

  • ViewDidLoad後にクロージャーを用いて処理が終わった後にmakeViewを行なう
  • ViewControllerのライフサイクル を意識して適切なところで処理を入れる

ライフサイクルを理解してViewが読み込まれた後にViewを作成してあげると解決した。

ライフサイクル についての記事UIViewControllerのライフサイクルがとても分かりやすかった。

どこでViewが更新されているのか

viewwillLayoutSubviews以降の処理

それぞれのライフサイクル で調べてみた


viewDidLoad(355.0, 278.5)
viewwillAppear(355.0, 278.5)
2020-07-18 11:34:13.851786+0900 S Player Plus[26679:11650844] Metal API Validation Enabled
viewwillLayoutSubviews(355.0, 278.5)
viewwillLayoutSubviews(355.0, 322.5)
viewdidLayoutSubviews(394.0, 383.0)

上のコードをみるとviewwillLayoutSubviewsでViewが更新されている。

したがってここに自作Viewを作成してあげると問題が解決します。がviewwillLayoutSubviewsは複数回呼ばれるので注意が必要


//Viewのレイアウト処理 複数回呼ばれる
override func viewWillLayoutSubviews() {}
override func viewDidLayoutSubviews() {}
//レイアウト処理終了後
override func viewDidAppear(_ animated: Bool) {}

最後に

アプリ開発でviewDidLoad()などのメソッドはおまじないのように使っていましたが、今回の問題解決からライフサイクルを意識したコードを書くことができました。

Viewの描画がバグる時は参考にしてみてください!

参考文献

viewDidLoad, viewWillAppearなどの使い分けの例 - 未熟エンジニアのブログ

1
1
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
1
1