Quando minhas "linhas" UIStackView são comprimidas, elas jogam AutoLayout
avisos. No entanto, eles são exibidos corretamente e nada mais está errado além desses tipos de registros:
Incapaz de satisfazer as restrições simultaneamente. Provavelmente, pelo menos uma das restrições na lista a seguir é aquela que você não deseja. Experimente o seguinte: (1) observe cada restrição e tente descobrir qual você não espera; (2) encontre o código que adicionou a restrição ou restrições indesejadas e corrija-o. (Observação: se você perceber
NSAutoresizingMaskLayoutConstraints
que não entende, consulte a documentação daUIView
propriedadetranslatesAutoresizingMaskIntoConstraints
) (
Então, eu não tenho certeza de como consertar isso ainda, mas não parece quebrar nada além de ser irritante.
Alguém sabe como resolver isso? Curiosamente, as restrições de layout são frequentemente marcadas com 'ocultação de UISV' , indicando que talvez deva ignorar os mínimos de altura para subvisualizações ou algo assim neste caso.
fonte
Respostas:
Você tem esse problema porque ao definir uma subvisualização de dentro
UIStackView
para oculta, ela primeiro restringirá sua altura a zero para animá-la.Eu estava recebendo o seguinte erro:
O que eu estava tentando fazer era colocar um
UIView
dentro do meuUIStackView
que continha umaUISegmentedControl
inserção de 8pts em cada borda.Quando eu defini como oculto, ele tentaria restringir a visualização do contêiner a uma altura zero, mas como eu tenho um conjunto de restrições de cima para baixo, houve um conflito.
Para resolver o problema, mudei minha prioridade de restrição superior e inferior de 8pt de 1000 para 999 para que a
UISV-hiding
restrição possa ter prioridade, se necessário.fonte
Eu estava tendo um problema semelhante que não era fácil de resolver. No meu caso, eu tinha uma visão de pilha embutida em uma visão de pilha. O UIStackView interno tinha dois rótulos e um espaçamento diferente de zero especificado.
Quando você chama addArrangedSubview (), ele cria automaticamente restrições semelhantes às seguintes:
Agora, quando você tenta ocultar o innerStackView, recebe um aviso de restrições ambíguas.
Para entender o porquê, primeiro vamos ver por que isso não acontece quando
innerStackView.spacing
é igual a0
. Quando você chamainnerStackView.hidden = true
, @liamnichols estava correto ... oouterStackView
irá interceptar magicamente esta chamada e criar uma restrição de ocultação de UISV de0
altura com prioridade 1000 (obrigatório). Presumivelmente, isso permite que os elementos na visualização da pilha sejam animados fora da visualização, no caso de seu código oculto ser chamado dentro de um bloco. Infelizmente, não parece haver uma maneira de evitar que essa restrição seja adicionada. No entanto, você não receberá um aviso "Incapaz de satisfazer as restrições simultaneamente" (USSC), uma vez que acontece o seguinte:UIView.animationWithDuration()
É claro que essas 4 restrições podem ser satisfeitas. A visualização em pilha simplesmente transforma tudo em um pixel de altura 0.
Agora voltando ao exemplo de buggy, se definir o
spacing
que2
, agora temos essas restrições:A visualização da pilha não pode ter 0 pixels de altura e seu conteúdo ter 2 pixels de altura. As restrições não podem ser satisfeitas.
Observação: você pode ver esse comportamento com um exemplo mais simples. Basta adicionar um UIView a uma exibição de pilha como uma subvisualização organizada. Em seguida, defina uma restrição de altura nesse UIView com prioridade 1000. Agora tente chamar hide sobre isso.
Nota: Por alguma razão, isso só acontecia quando minha visão de pilha era uma subvisão de UICollectionViewCell ou UITableViewCell. No entanto, você ainda pode reproduzir esse comportamento fora de uma célula chamando
innerStackView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize)
no próximo loop de execução depois de ocultar a exibição da pilha interna.Nota: Mesmo se você tentar executar o código em um UIView.performWithoutAnimations, a visualização da pilha ainda adicionará uma restrição de altura 0 que causará o aviso USSC.
Existem pelo menos 3 soluções para este problema:
spacing
para 0. Isso é irritante porque você precisa reverter o processo (e lembrar o espaçamento original) sempre que mostrar o conteúdo novamente.removeFromSuperview
. Isso é ainda mais irritante, pois ao reverter o processo, você precisa se lembrar onde inserir o item removido. Você poderia otimizar apenas chamando removeArrangedSubview e, em seguida, ocultando, mas ainda há muitos registros que precisam ser feitos.spacing
) em um UIView. Especifique pelo menos uma restrição como prioridade não obrigatória (999 ou abaixo). Esta é a melhor solução, já que não é necessário fazer nenhuma contabilidade. No meu exemplo, criei as restrições superior, inicial e final em 1000 entre a visualização da pilha e a visualização do wrapper e, em seguida, criei uma restrição 999 da parte inferior da visualização da pilha até a visualização do wrapper. Dessa forma, quando a visualização da pilha externa cria uma restrição de altura zero, a restrição 999 é quebrada e você não vê o aviso USSC. (Observação: isso é semelhante à solução para o caso de contentView.translatesAutoResizingMaskToConstraints de uma subclasse UICollectionViewCell ser definido comofalse
)Em resumo, os motivos pelos quais você obtém esse comportamento são:
Se a Apple (1) tivesse permitido que você especificasse a prioridade das restrições (especialmente de espaçadores) ou (2) tivesse permitido que você desistisse da restrição automática de ocultação de UISV , este problema seria facilmente resolvido.
fonte
UIStackView
filho de umaUIStackView
precisa ser envolvido em umUIView
ou apenas aquele que você está tentando ocultar / revelar?UIStackView
tendem a ser enigmáticos e difíceis de entender.Na maioria das vezes, esse erro pode ser resolvido diminuindo a prioridade das restrições para eliminar conflitos.
fonte
Quando você define uma visualização como oculta, o
UIStackview
tentará animá-la. Se você quiser esse efeito, precisará definir a prioridade certa para as restrições para que não entrem em conflito (como muitos sugeriram acima).No entanto, se você não se importa com a animação (talvez a esteja escondendo em ViewDidLoad), então você pode simplificar, o
removeFromSuperview
que terá o mesmo efeito, mas sem problemas com restrições, já que elas serão removidas junto com a visualização.fonte
Com base na resposta de @ Senseful, aqui está uma extensão UIStackView para envolver uma visualização de pilha em uma visualização e aplicar as restrições que ele recomenda:
Em vez de adicionar seu
stackView
, usestackView.wrapped()
.fonte
Primeiro, como outros sugeriram, certifique-se de que as restrições que você pode controlar, ou seja, não as restrições inerentes ao UIStackView, estão definidas com a prioridade 999, para que possam ser substituídas quando a visualização estiver oculta.
Se você ainda estiver tendo o problema, é provável que o problema seja devido ao espaçamento nas StackViews ocultas. Minha solução foi adicionar um UIView como espaçador e definir o espaçamento UIStackView como zero. Em seguida, defina as restrições View.height ou View.width (dependendo de uma pilha vertical ou horizontal) para o espaçamento de StackView.
Em seguida, ajuste as prioridades de envolvimento de conteúdo e resistência à compressão de conteúdo de suas visualizações recém-adicionadas. Você também pode ter que alterar a distribuição do StackView pai.
Todos os itens acima podem ser feitos no Interface Builder. Além disso, você pode ter que ocultar / mostrar algumas das visualizações recém-adicionadas programaticamente para que não haja espaçamento indesejado.
fonte
Recentemente, lutei com erros de layout automático ao ocultar um
UIStackView
. Em vez de fazer um monte de guarda de livros e empacotamentoUIViews
, optei por criar uma saída para o meuparentStackView
e para as crianças que quero ocultar / mostrar.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,
parentStackViews
contém uma matriz dos 4 elementos: Top Stack View, StackViewNumber1, Stack View número 2 e botão Stop. Seus índicesarrangedSubviews
são 0, 1, 2 e 3, respectivamente. Quando desejo ocultar um, simplesmente o removo doparentStackView's
arrangedSubviews
array. 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
arrangedSubviews
array.3) Ligue
self.view.layoutIfNeeded()
comUIView.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:
Em seguida, anime-o:
Se você quiser "mostrar" um
stackViewNumber2
depois, basta inseri-lo noparentStackView
arrangedSubViews
índice desejado e animar a atualização.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
viewDidLoad
e atualizá-lo sem usar a animaçãoview.layoutIfNeeded()
.fonte
Eu experimentei os mesmos erros com Stack Views incorporado, embora tudo funcionasse bem no tempo de execução.
Resolvi os erros de restrição ocultando todas as visualizações da subpilha primeiro (configuração
isHidden = true
) antes de ocultar a visualização da pilha pai.Fazer isso não envolvia toda a complexidade de remover visualizações suborganizadas, mantendo um índice para quando fosse necessário adicioná-las novamente.
Espero que isto ajude.
fonte
A Senseful forneceu uma excelente resposta para a raiz do problema acima, então irei direto para a solução.
Tudo o que você precisa fazer é definir a prioridade de todas as restrições stackView abaixo de 1000 (999 fará o trabalho). Por exemplo, se stackView estiver restrito à esquerda, direita, superior e inferior para sua supervisão, todas as 4 restrições devem ter prioridade inferior a 1000.
fonte
Você pode ter criado uma restrição ao trabalhar com uma determinada classe de tamanho (ex: wCompact hRegular) e, em seguida, criado uma duplicata quando alternou para outra classe de tamanho (ex: wAny hAny). verifique as restrições dos objetos de interface do usuário em classes de tamanho diferentes e veja se há anomalias nas restrições. você deve ver as linhas vermelhas indicando restrições de colisão. Não posso colocar uma foto antes de obter 10 pontos de reputação, desculpe: /
fonte
Eu queria ocultar UIStackViews inteiros de uma vez, mas estava recebendo os mesmos erros do OP, isso corrigiu para mim:
fonte
priority = 1000
) para não obrigatória (priority <= 999
).Eu tinha uma linha de botões com restrição de altura. Isso acontece quando um botão está oculto. Definir a prioridade dessa restrição de altura dos botões para 999 resolveu o problema.
fonte
Este erro não tem nada a ver com UIStackView. Acontece quando você tem restrições de conflito com as mesmas prioridades. Por exemplo, se você tiver uma restrição afirma que a largura da sua visualização é 100, e você tem outra restrição ao mesmo tempo que afirma que a largura da visualização é 25% de seu contêiner. Obviamente, existem duas restrições conflitantes. A solução é excluir um deles.
fonte
NOP com [mySubView removeFromSuperview]. Espero que possa ajudar alguém :)
fonte