Parece que com o Xcode 8 viewDidLoad
ativado, todas as subvisualizações do viewcontroller têm o mesmo tamanho de 1000x1000. Coisa estranha, mas tudo bem, viewDidLoad
nunca foi o melhor lugar para dimensionar corretamente as visualizações.
Mas viewDidLayoutSubviews
é!
E no meu projeto atual, tento imprimir o tamanho de um botão:
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
NSLog(@"%@", self.myButton);
}
O log mostra um tamanho de (1000x1000) para myButton! Então, se eu logar em um clique de botão, por exemplo, o log mostra um tamanho normal.
Estou usando autolayout.
É um bug?
ios
autolayout
ios10
xcode8
Martin
fonte
fonte
(0, 0, 1000, 1000)
inicialização associada é a nova maneira que o Xcode instancia visualizações do IB. Antes do Xcode8, as visualizações eram criadas com seu tamanho configurado no xib, e redimensionadas de acordo com a tela logo depois. Mas agora, não há tamanho configurado no documento IB, pois o tamanho depende da seleção do seu dispositivo (na parte inferior da tela). Portanto, a verdadeira questão é: há um lugar confiável onde o tamanho final das visualizações possa ser verificado?Respostas:
Agora, o Interface Builder permite que o usuário altere dinamicamente o tamanho de todos os controladores de visualização no storyboard, para simular o tamanho de um determinado dispositivo.
Antes desta funcionalidade, o usuário deve definir manualmente cada tamanho do controlador de visualização. Portanto, o controlador de visualização foi salvo com um certo tamanho, que foi usado
initWithCoder
para definir o quadro inicial.Agora, parece que
initWithCoder
não use o tamanho definido no storyboard, e defina um tamanho de 1000x1000 px para a visualização do controlador de visualização e todas as suas subvisualizações.Isso não é um problema, porque as visualizações devem sempre usar uma destas soluções de layout:
autolayout, e todas as restrições farão o layout correto de suas visualizações
autoresizingMask, que fará o layout de cada visualização que não tenha nenhuma restrição anexada ( observe que o autolayout e as restrições de margem agora são compatíveis na mesma visualização \ o /! )
Mas isso é um problema para todas as coisas de layout relacionadas à camada de visualização, como
cornerRadius
, desde que nem autolayout nem máscara de redimensionamento automático se aplicam às propriedades da camada.Para responder a esse problema, a maneira comum é usar
viewDidLayoutSubviews
se você estiver no controlador oulayoutSubview
em uma visualização. Neste ponto (não se esqueça de chamar seussuper
métodos relativos), você tem certeza de que todas as coisas de layout foram feitas!Tem certeza? Hum ... não totalmente, eu observei, e é por isso que fiz essa pergunta, em alguns casos a visualização ainda tem seu tamanho 1000x1000 neste método. Acho que não há resposta para minha própria pergunta. Para dar o máximo de informações sobre isso:
1- acontece apenas no layout das células! Em
UITableViewCell
&UICollectionViewCell
subclasses,layoutSubview
não será chamado depois que as subvisualizações forem dispostas corretamente.2- Como @EugenDimboiu comentou (por favor, vote a favor da resposta se for útil para você), chamar
[myView layoutIfNeeded]
a subvisão sem layout irá exibi-la corretamente na hora certa.3- Na minha opinião, esse é definitivamente um bug. Enviei-o ao radar (id 28562874).
PS: Não sou inglês nativo, então fique à vontade para editar minha postagem se minha gramática precisar ser corrigida;)
PS2: Se você tiver alguma solução melhor, fique à vontade para não escrever outra resposta. Vou mover a resposta aceita.
fonte
UIStackView
interna de umaUICollectionViewCell
não estava voltando na altura correta duranteviewDidLayoutSubviews
. LigarlayoutIfNeeded
imediatamente corrigiu o problema.Você está usando cantos arredondados para o botão? Tente ligar
layoutIfNeeded()
antes.fonte
Solução: Enrole tudo dentro
viewDidLayoutSubviews
emDispatchQueue.main.async
.fonte
-viewDidLoad
... uma solução tão estranhaSei que essa não era sua pergunta exata, mas me deparei com um problema semelhante em que, como na atualização, algumas das minhas visualizações estavam confusas, apesar de ter o tamanho de quadro correto em viewDidLayoutSubviews. De acordo com as notas de lançamento do iOS 10:
Essencialmente, você não pode chamar layoutIfNeeded em um objeto filho de View se estiver usando translatesAutoresizingMaskIntoConstraints - agora, chamar layoutIfNeeded deve estar em superView e você ainda pode chamar isso em viewDidLayoutSubviews.
fonte
Se os quadros não estiverem corretos em layoutSubViews (o que não é verdade), você pode enviar um pouco de código assíncrono na thread principal. Isso dá ao sistema algum tempo para fazer o layout. Quando o bloco que você despacha é executado, os quadros têm seus tamanhos adequados.
fonte
Isso corrigiu o problema (ridiculamente irritante) para mim:
Editar / Nota: Isso é para um ViewController de tela inteira.
fonte
[super viewDidLayoutSubviews];
este método por causa de muitas coisas de autolayout feitas pela própria visualizaçãoUIView
s. Mas se você deve realizar cálculos especiais em um determinado quadro de visão, a resposta de Eugen funciona: chamelayoutIfNeeded
-o. Tenho a sensação de que esta não é a melhor solução, mas ainda não encontrei nenhuma melhor.Na verdade,
viewDidLayoutSubviews
também não é o melhor lugar para definir o quadro de sua visão. Pelo que entendi, de agora em diante, o único lugar em que isso deve ser feito é olayoutSubviews
método no código da visão real. Eu queria não estar certo, alguém me corrija por favor se não é verdade!fonte
viewDidLayoutSubviews
é bastante ambígua. A segunda frase em "discussões" contradiz de alguma forma a última. developer.apple.com/reference/uikit/uiviewcontroller/…Eu já relatei esse problema para a apple, esse problema existe há muito tempo, quando você está inicializando o UIViewController do Xib, mas achei uma boa solução. Além disso, descobri esse problema em alguns casos quando layoutIfNeeded em UICollectionView e UITableView quando a fonte de dados não está definida no momento inicial e também precisei fazer um swizzle.
Enviar uma vez a extensão:
Extensão Swizzle:
fonte
Meu problema foi resolvido alterando o uso de
para
Então, de fez para vontade
Super estranho
fonte
Melhor solução para mim.
Usando
fonte
Substitua layoutSublayers (da camada: CALayer) em vez de layoutSubviews na subvisualização da célula para ter quadros corretos
fonte
Se você precisar fazer algo com base no quadro de sua visão - sobrescreva layoutSubviews e chame layoutIfNeeded
Tive o problema de viewDidLayoutSubviews retornando o quadro errado para minha visualização, para o qual precisei adicionar um gradiente. E apenas layoutIfNeeded fez a coisa certa :)
fonte
De acordo com a nova atualização no ios, isso é na verdade um bug, mas podemos reduzir isso usando -
Se você estiver usando xib com autolayout em seu projeto, então você tem que apenas atualizar o quadro na configuração de autolayout, encontre a imagem para isso.
fonte