Recentemente, lutei com erros de layout automático ao ocultar um UIStackView. Em vez de fazer um monte de guarda de livros e empacotamento UIViews, optei por criar uma saída para o meu parentStackViewe para as crianças que quero ocultar / mostrar.
@IBOutlet weak var parentStackView: UIStackView!
@IBOutlet var stackViewNumber1: UIStackView!
@IBOutlet var stackViewNumber2: UIStackView!
No storyboard, minha pilha pai se parece com:

Ele tem 4 filhos e cada um deles tem várias visualizações de pilha dentro deles. Quando você oculta uma visualização de pilha, se ela tiver elementos de interface do usuário que também são visualizações de pilha, você verá um fluxo de erros de layout automático. Em vez de me esconder, optei por removê-los.
No meu exemplo, parentStackViewscontém uma matriz dos 4 elementos: Top Stack View, StackViewNumber1, Stack View número 2 e botão Stop. Seus índices arrangedSubviewssão 0, 1, 2 e 3, respectivamente. Quando desejo ocultar um, simplesmente o removo do parentStackView's arrangedSubviewsarray. Como não é fraco, ele permanece na memória e você pode simplesmente colocá-lo de volta no índice desejado mais tarde. Não estou reinicializando-o, então ele permanece até que seja necessário, mas não incha a memória.
Então, basicamente, você pode ...
1) Arraste IBOutlets para a pilha pai e os filhos que deseja ocultar / mostrar para o storyboard.
2) Quando você quiser ocultá-los, remova a pilha que deseja ocultar do parentStackView's arrangedSubviewsarray.
3) Ligue self.view.layoutIfNeeded()com UIView.animateWithDuration.
Observe que os dois últimos stackViews não são weak. Você precisa mantê-los por perto para quando você os revelar.
Digamos que eu queira ocultar stackViewNumber2:
parentStackView.removeArrangedSubview(stackViewNumber2)
stackViewNumber2.removeFromSuperview()
Em seguida, anime-o:
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
Se você quiser "mostrar" um stackViewNumber2depois, basta inseri-lo no parentStackView arrangedSubViewsíndice desejado e animar a atualização.
parentStackView.removeArrangedSubview(stackViewNumber1)
stackViewNumber1.removeFromSuperview()
parentStackView.insertArrangedSubview(stackViewNumber2, at: 1)
// Then animate it
UIView.animate(withDuration: 0.25,
delay: 0,
usingSpringWithDamping: 2.0,
initialSpringVelocity: 10.0,
options: [.curveEaseOut],
animations: {
self.view.layoutIfNeeded()
},
completion: nil)
Descobri que isso é muito mais fácil do que fazer contabilidade sobre as restrições, mexer nas prioridades etc.
Se você deseja ocultar algo por padrão, pode simplesmente colocá-lo no storyboard, removê-lo viewDidLoade atualizá-lo sem usar a animação view.layoutIfNeeded().