質問: ベースとなるViewを生成し、その上に機能に応じたUIパーツを`addSubView()`します。 その後機能を変えた場合はベースとなるViewの上のUIパーツを全て`removeFromSuperview()`してから値を再設定し`addSubView()`という処理を行ったのですが、 再設定後の表示が画面の左上にUIパーツがまとまった状態になり、Debug View Hierarchyで確認するとRuntimeErrorに以下のエラーが出ていました。 ``` Layout Issues -> Position is ambiguous for UILabel ``` StoryBoard上でAutoLayoutは設定はしてあります。 なので、再設定をしない初回は正しく表示されます。 `removeFromSuperview()`をした場合、インスタンスは解放されずViewとの繋がりが絶たれるだけだという認識でいたので、制約が解除されるという想定はしていませんでしたが、 UIパーツの制約が解除されてしまうということはあるのでしょうか?
回答: > > `removeFromSuperview()`をした場合、インスタンスは解放されずViewとの繋がりが絶たれるだけだという認識でいたので、 > > > その認識は正しくありません。あるViewは、Superview以外のオブジェクトから強参照されていない場合、解放されます。そしてAuto Layoutによる制約(Constraint)は、この「Superview以外のオブジェクト」にはあたりません。 ここで「解放する」とは、いつでも解放されていい状態にするという意味で使われていて、直ちに解放することではないので、オブジェクトの監視システムが解放する直前の限られたタイミングで、`nil`をチェックすると、アドレスが取得できたりすることがあります。 こういう時は、検証用のプログラムを作ってみるといいでしょう。 ひとつの`UILabel`と、ふたつの`UIButton`を作ります。インスタンス`label`は、Storyboard上で、Constraintの設定をしておいてください。 ``` import UIKit class ViewController: UIViewController { @IBOutlet weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() } @IBAction func removeLabel(_ sender: AnyObject) { label.removeFromSuperview() } @IBAction func nilCheck(_ sender: AnyObject) { if label == nil { print("Label is nil") } else { print("Label is not nil") } } } ``` `removeLabel()`のボタンを押して、次に`nilCheck()`のボタンを押してください。 > > 出力:Label is nil > > > Storyboard/Interface Builderで配置したViewは、`removeFromSuperview()`しない。表示からViewを消したければ、`isHidden`(Swift2以前では、`hidden`)で、非表示にする方法を選ぶ。非表示にした場合、Constraintは維持しています。