Ho una UIView che viene posizionata sullo schermo tramite diversi vincoli. Alcuni dei vincoli sono di proprietà della superview, altri sono di proprietà di altri antenati (ad esempio, forse la proprietà view di un UIViewController).
Voglio rimuovere tutti questi vecchi vincoli e posizionarli in un posto nuovo usando nuovi vincoli.
Come posso farlo senza creare un IBOutlet per ogni singolo vincolo e dover ricordare quale vista possiede detto vincolo?
Per elaborare, l'approccio ingenuo sarebbe quello di creare un gruppo di IBOutlet per ciascuno dei vincoli e quindi implicherebbe la chiamata di codice come:
[viewA removeConstraint:self.myViewsLeftConstraint];
[viewB removeConstraint:self.myViewsTopConstraint];
[viewB removeConstraint:self.myViewsBottomConstraint];
[self.view removeConstraint:self.myViewsRightConstraint];
Il problema con questo codice è che anche nel caso più semplice, avrei bisogno di creare 2 IBOutlet. Per layout complessi, questo potrebbe facilmente raggiungere 4 o 8 IBOutlet richiesti. Inoltre, dovrei assicurarmi che la mia richiesta di rimuovere il vincolo venga richiamata sulla visualizzazione corretta. Ad esempio, immagina che myViewsLeftConstraint
sia di proprietà di viewA
. Se dovessi chiamare accidentalmente [self.view removeConstraint:self.myViewsLeftConstraint]
, non accadrebbe nulla.
Nota: il metodo constraintsAffectingLayoutForAxis sembra promettente, ma è inteso solo a scopo di debug.
Aggiornamento: Molte delle risposte che sto ricevendo accordo con self.constraints
, self.superview.constraints
o qualche variante di quelli. Queste soluzioni non funzioneranno poiché quei metodi restituiscono solo i vincoli posseduti dalla vista, non quelli influenzano la vista.
Per chiarire il problema con queste soluzioni, considera questa gerarchia di visualizzazione:
- Nonno
- Padre
- Me
- Figlio
- Figlia
- Fratello
- Me
- Zio
- Padre
Ora immagina di creare i seguenti vincoli e di collegarli sempre al loro antenato comune più vicino:
- C0: Me: stesso top di Son (di mia proprietà)
- C1: Me: width = 100 (di mia proprietà)
- C2: Io: stessa altezza del fratello (di proprietà del padre)
- C3: Io: stesso top di Uncle (di proprietà del nonno)
- C4: Io: stesso a sinistra del nonno (di proprietà del nonno)
- C5: Brother: stesso a sinistra di Father (di proprietà di Father)
- C6: Zio: stesso a sinistra del nonno (di proprietà del nonno)
- C7: Figlio: stesso a sinistra di Daughter (di mia proprietà)
Ora immagina di voler rimuovere tutti i vincoli che interessano Me
. Qualsiasi soluzione adeguata dovrebbe rimuovere [C0,C1,C2,C3,C4]
e nient'altro.
Se uso self.constraints
(dove il sé è Me), otterrò [C0,C1,C7]
, poiché questi sono gli unici vincoli posseduti da Me. Ovviamente non basterebbe rimuoverlo visto che manca [C2,C3,C4]
. Inoltre, sta rimuovendo C7
inutilmente.
Se uso self.superview.constraints
(dove io sono io), otterrò [C2,C5]
, poiché quelli sono i vincoli posseduti da Padre. Ovviamente non possiamo rimuovere tutti questi poiché C5
è completamente estraneo a Me
.
Se uso grandfather.constraints
, otterrò [C3,C4,C6]
. Ancora una volta, non possiamo rimuoverli tutti poiché C6
dovrebbero rimanere intatti.
L'approccio della forza bruta consiste nel fare un loop su ciascuno degli antenati della vista (inclusa se stessa) e vedere se firstItem
o secondItem
sono la vista stessa; in tal caso, rimuovere tale vincolo. Questo porterà a una soluzione corretta, tornando[C0,C1,C2,C3,C4]
e solo quei vincoli.
Tuttavia, spero che esista una soluzione più elegante rispetto al dover scorrere l'intero elenco degli antenati.