2015-05-07 10 views
5

Sto utilizzando systemLayoutSizeFittingSize per ottenere la dimensione minima per una sottoclasse di visualizzazione personalizzata che soddisfi i suoi vincoli interni.Vincolo "UITemporaryLayoutHeight" iOS

let someView = SomeView()   
someView.setNeedsUpdateConstraints() 
someView.setNeedsLayout() 
someView.layoutIfNeeded() 

let viewSize = someView.systemLayoutSizeFittingSize(UILayoutFittingCompressedSize) 

println(viewSize) // PRINTS (0.0, 96.0) WHICH IS RIGHT! 

ottengo il valore corretto, ma ho anche ricevuto un avviso Unable to simultaneously satisfy constraints:

"<NSLayoutConstraint:0x7ff16b753190 '_UITemporaryLayoutHeight' V:[ProjectName.SomeView:0x7ff16b772210(0)]>", 
"<NSLayoutConstraint:0x7ff16b75de50 UIImageView:0x7ff16b76eff0.top == ProjectName.SomeView:0x7ff16b772210.topMargin>", 
"<NSLayoutConstraint:0x7ff16b7653f0 UIImageView:0x7ff16b76eff0.bottom <= ProjectName.SomeView:0x7ff16b772210.bottomMargin>" 

Qui di seguito è il mio SomeView UIView sottoclasse.

Contiene solo un'immagine 80x80 fissata ai margini superiore, sinistro e inferiore. (Sto usando PureLayout per scrivere vincoli).

Ora ovviamente questa vista avrà un'altezza fissa di 96 (80 + 8x2 per i margini) ma teoricamente potrebbe allungarsi se le sue sottoview cambiano dimensione.

Qualche idea? Ricerca Google per UITemporaryLayoutHeight (o larghezza) dà 0 risultati ...

class SomeView: UIView { 

    let imageView = UIImageView() 

    var constraintsSet = false 

    override init(frame: CGRect) { 

     super.init(frame: frame) 

     backgroundColor = UIColor.lightGrayColor() 

     imageView.backgroundColor = UIColor.darkGrayColor() 
     addSubview(imageView) 
    } 

    override func updateConstraints() { 

     if(!constraintsSet) { 

      imageView.autoPinEdgeToSuperviewMargin(.Top) 
      imageView.autoPinEdgeToSuperviewMargin(.Left) 
      imageView.autoPinEdgeToSuperviewMargin(.Bottom, relation: NSLayoutRelation.GreaterThanOrEqual) 
      imageView.autoSetDimension(.Width, toSize: 80.0) 
      imageView.autoSetDimension(.Height, toSize: 80.0) 

      constraintsSet = true 
     } 
     super.updateConstraints() 
    } 
} 

risposta

14

Questo:

Esso contiene solo un ImageView 80x80 bloccato verso l'alto, i margini sinistro e inferiore

e questo

NSLayoutConstraint: 0x7ff16b753190 V '_UITemporaryLayoutHeight': [ ProjectName.SomeView: 0x7ff16b772210 (0)]

è la fonte del problema. UIKit è a un certo punto nel processo di caricamento/layout/visualizzazione utilizzando un'altezza pari a 0. Dato che hai limiti sia in alto che in basso, e, la dimensione dell'immagine ha una dimensione di contenuto intrinseco, stai dicendo di adattarla all'immagine in verticale zero spazio.

Il solito modo per risolvere questo problema è impostare la priorità del vincolo superiore o inferiore su qualsiasi valore inferiore a 1000.

+1

Come nota a margine: mi piacerebbe molto sentire le spiegazioni di Apple su questi _UITemporaryLayoutHeight e cose simili che appaiono nella console. –

+0

Grazie, sembra risolvere il problema! – LorTush

+0

Qualcuno si prega di chiedere ai laboratori WWDC e riferire. La mia ipotesi: hanno messo il limite lì per rendere il sistema operativo esplicitamente richiamare la tua vista per non essere felice di essere ridotto a 0 dimensioni. –

0

Il luogo in cui si sta aggiungendo i vincoli sembra essere l'origine del problema.

Inoltre, è necessario impostare setTranslatesAutoresizingMaskIntoConstraints(false) al imageView

Prova ad aggiungere i vincoli quando si aggiunge l'immagine come visualizzazione secondaria.

Qualcosa del genere dovrebbe funzionare:

class SomeView: UIView { 

    let imageView = UIImageView() 

    var constraintsSet = false 

    override init(frame: CGRect) { 

     super.init(frame: frame) 

     backgroundColor = UIColor.lightGrayColor() 

     imageView.backgroundColor = UIColor.darkGrayColor() 
     addSubview(imageView) 

     // Don't forget this 
     imageView.setTranslatesAutoresizingMaskIntoConstraints(false) 

     imageView.autoPinEdgeToSuperviewMargin(.Top) 
     imageView.autoPinEdgeToSuperviewMargin(.Left) 
     imageView.autoPinEdgeToSuperviewMargin(.Bottom, relation: NSLayoutRelation.GreaterThanOrEqual) 
     imageView.autoSetDimension(.Width, toSize: 80.0) 
     imageView.autoSetDimension(.Height, toSize: 80.0) 
    } 
} 

Spero che questo lavoro. Fammi sapere se hai bisogno di più aiuto!

+0

Grazie per la risposta! Sono abbastanza sicuro che PureLayout imposta automaticamente setTranslatesAutoresizingMaskIntoConstraints su false, quindi è per questo che l'ho lasciato fuori. Riguardo al punto in cui aggiungo i vincoli, ho letto in molti punti (inclusi i documenti Apple) che i vincoli devono essere aggiunti in updateConstraints () metodo. Ho provato a spostarle nel metodo init() e Ho ricevuto un avviso diverso: ' ""' Altezza ancora viene impostato su 0, ma senza il nome 'UITemporaryLayoutHeight' – LorTush

13

Ho notato che questo mi succede se chiamo layoutIfNeeded su una vista prima che il suo genitore è stato disposto. Scommetto che se hai rimosso someView.layoutIfNeeded() non vedresti più quell'errore. Probabilmente potresti anche liberarti di someView.setNeedsLayout() e sostituirlo con someView.updateConstraintsIfNeeded(). systemLayoutSizeFittingSize non dovrebbe richiedere che le viste siano effettivamente disposte, ma ha solo bisogno che i vincoli siano configurati correttamente.

+0

ottimo! Funziona. –

2

Ho ricevuto questo avviso quando la vista non dispone di superview e layoutIfNeeded. La mia soluzione era chiamare layoutIfNeeded dopo aver aggiunto la vista su un superview. Spero che questo aiuti:

- (void)didMoveToSuperview { 
    [super didMoveToSuperview]; 
    [self layoutIfNeeded]; 
} 
+0

Perché qualcuno ha votato questo? Questo funziona totalmente per me. Mi piacerebbe sapere perché comunque. –

+2

Questo ha funzionato per me. layoutIfNeeded stava causando problemi su una vista senza superview. – grez