UIKitのisHiddenを二値だと信じてはいけない
先週、なぜかコード的にはおかしくないはずなのに、Viewの表示状態が壊れるという現象に遭遇しました。
どうも調べてみると、isHidden
で代入しても値が反映されないようでした。
もちろん、MainThreadであることは確認しています。
調べてみると、stack overflowでisHidden
は累積するという指摘がいくつか見つかったので、以下のコードで処理するようにしたら、確かにこの現象は治りました。
いやいやいやいや。そんな馬鹿な。
この現象は再現性があるものの(プロダクトコードで再現手順が確立されている)、どうも他のViewで似たようなことを行っても発生しない。ということで、stack overflowの情報を元に再現を試みてみることにしました。
再現方法
結論から言うと、分かりやすい再現はできませんでしたが、一応の再現コードは作れました。
- https://github.com/soranoba/iOS-SandBox/tree/UIKit-cumulative-hidden をクローンして適当なシュミレータ、もしくは実機で起動する。
- この行にbreak pointを設定する
- 右90度 -> 左90度で回転させた後、UISegmentedControlの真ん中 (Second) を選択する
- 設定したbreak pointで止まる
何回か見た目が壊れる(2色ではなく1色の表示になる)ケースも確認しているので、ここからもう少しこねくり回せば、いい感じの再現コードになりそうです。
そして、どうも以下の3つを満たす場合に発生する節があります。
isHidden
を操作する対象のViewが、StackViewの中にあること- アニメーション中に
isHidden
の操作を行うこと - 現状の値と同じ値を設定すること
Objective-Cではpropertyへのアクセスにgetterとsetterを経由する都合上、そこでどんな処理をされているか分からないので、値の設定が反映されないということはあり得ますが、なんとも不思議なものです。
このコードでは確認できませんでしたがプロダクトコードの方では3回true
を設定すれば3回false
を設定しないと戻らなかったので、累積値になる場合があることも確かなようです。
アニメーション中にisHidden
を操作しなければ良いとはいえ、Portrait or Landscapeともう一つの状態によって表示/非表示の操作するケースは割とよくあるので何とも困ったものです。
参考文献
- Swift: Disappearing views from a stackViewswift-disappearing-views-from-a-stackview
- Can’t change UIView.isHidden property after action is called by UIBarButton
記事が気に入ったらチップを送ることができます!
You can give me a cup of coffee :)
Kyash ID: soranoba
Amazon: Wish List
GitHub Sponsor: github.com/sponsors/soranoba
PayPal.Me: paypal.me/soranoba
(Updated: )