zapatos www unidos the tarjeta servicio pagina pagar mexico estados español cliente childrensplace childrens ios swift nslayoutconstraint

ios - www - ¿Cómo “encontrar” tu propia restricción?



www.childrensplace.com en español (3)

Podría ahorrarle a alguien algo de escribir .......

Basado en la respuesta ganadora de recompensas de stakri, aquí es exactamente cómo obtener

Todas las restricciones del tipo "ancho fraccional de otra vista"

Todas las restricciones del tipo "ancho de punto fijo"

Asi que ..

fileprivate extension UIView { func widthAsPointsConstraints()->[NSLayoutConstraint] {} func widthAsFractionOfAnotherViewConstraints()->[NSLayoutConstraint] {} }

Kode completo a continuación. Por supuesto, puedes hacer "altura" de la misma manera.

Por lo tanto, úsalos así ...

let cc = someView.widthAsFractionOfAnotherViewConstraints() for c in cc { c.changeToNewConstraintWith(multiplier: 0.25) }

o

let cc = someView.widthAsPointsConstraints() for c in cc { c.constant = 150.0 }

Además, en la parte inferior pegué en un código de demostración simple, ejemplo de salida ...

Aquí está el kode. V2 ...

fileprivate extension UIView { // experimental func allConstraints()->[NSLayoutConstraint] { var views = [self] var view = self while let superview = view.superview { views.append(superview) view = superview } return views.flatMap({ $0.constraints }).filter { constraint in return constraint.firstItem as? UIView == self || constraint.secondItem as? UIView == self } } func widthAsPointsConstraints()->[NSLayoutConstraint] { return self.allConstraints() .filter({ ( $0.firstItem as? UIView == self && $0.secondItem == nil ) }) .filter({ $0.firstAttribute == .width && $0.secondAttribute == .notAnAttribute }) } func widthAsFractionOfAnotherViewConstraints()->[NSLayoutConstraint] { func _bothviews(_ c: NSLayoutConstraint)->Bool { if c.firstItem == nil { return false } if c.secondItem == nil { return false } if !c.firstItem!.isKind(of: UIView.self) { return false } if !c.secondItem!.isKind(of: UIView.self) { return false } return true } func _ab(_ c: NSLayoutConstraint)->Bool { return _bothviews(c) && c.firstItem as? UIView == self && c.secondItem as? UIView != self && c.firstAttribute == .width } func _ba(_ c: NSLayoutConstraint)->Bool { return _bothviews(c) && c.firstItem as? UIView != self && c.secondItem as? UIView == self && c.secondAttribute == .width } // note that .relation could be anything: and we don''t mind that return self.allConstraints() .filter({ _ab($0) || _ba($0) }) } } extension NSLayoutConstraint { // typical routine to "change" multiplier fraction... @discardableResult func changeToNewConstraintWith(multiplier:CGFloat) -> NSLayoutConstraint { //NSLayoutConstraint.deactivate([self]) self.isActive = false let nc = NSLayoutConstraint( item: firstItem as Any, attribute: firstAttribute, relatedBy: relation, toItem: secondItem, attribute: secondAttribute, multiplier: multiplier, constant: constant) nc.priority = priority nc.shouldBeArchived = self.shouldBeArchived nc.identifier = self.identifier //NSLayoutConstraint.activate([nc]) nc.isActive = true return nc } }

Sólo un ejemplo de demostración ...

override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) _teste() delay(5) { print("changing any ''fraction fo another view'' style widths .../n/n") let cc = self.animeHolder.widthAsFractionOfAnotherViewConstraints() for c in cc { c.changeToNewConstraintWith(multiplier: 0.25) } self._teste() } delay(10) { print("changing any ''points'' style widths .../n/n") let cc = self.animeHolder.widthAsPointsConstraints() for c in cc { c.constant = 150.0 } self._teste() } } func _teste() { print("/n---- allConstraints") for c in animeHolder.allConstraints() { print("/n /(c)") } print("/n---- widthAsPointsConstraints") for c in animeHolder.widthAsPointsConstraints() { print("/n /(c)/n /(c.multiplier) /(c.constant)") } print("/n---- widthAsFractionOfAnotherViewConstraints") for c in animeHolder.widthAsFractionOfAnotherViewConstraints() { print("/n /(c)/n /(c.multiplier) /(c.constant)") } print("/n----/n") }

Digamos que tengo una vista,

class CleverView: UIView

En la clase personalizada, quiero hacer esto:

func changeWidth() { let c = ... find my own layout constraint, for "width" c.constant = 70 * Gameinfo.ImportanceOfEnemyFactor }

De manera similar, quiero poder "encontrar" así, la restricción (o supongo que, todas las restricciones, podría haber más de una) unida a uno de los cuatro bordes.

Por lo tanto, para revisar todas las restricciones que se me unen y encontrar las de ancho / alto, o incluso las relevantes para un borde dado (por ejemplo, "izquierda").

¿Algunas ideas?

Tal vez vale la pena señalar esta pregunta

Tenga en cuenta que (obviamente) estoy preguntando cómo hacerlo de forma dinámica / programática.

(Sí, puede decir "enlace a la restricción" o "usar una ID"; el punto principal del control de calidad es cómo encontrarlos sobre la marcha y trabajar de forma dinámica).

Si no está .constraints con las restricciones, tenga en cuenta que .constraints solo le da los fines almacenados "allí".


Realmente hay dos casos:

  1. Las restricciones con respecto al tamaño de una vista o las relaciones con las vistas descendientes se guardan en sí mismas
  2. Las restricciones entre dos vistas se guardan en el antepasado común más bajo de las vistas

Repetir. Para restricciones que se encuentran entre dos vistas. De hecho, iOS siempre los almacena en el antepasado común más bajo. Por lo tanto, siempre se puede encontrar una restricción de una vista buscando en todos los antepasados ​​de la vista.

Por lo tanto, necesitamos verificar la vista en sí misma y todas sus supervisiones para ver si hay restricciones. Un enfoque podría ser:

extension UIView { // retrieves all constraints that mention the view func getAllConstraints() -> [NSLayoutConstraint] { // array will contain self and all superviews var views = [self] // get all superviews var view = self while let superview = view.superview { views.append(superview) view = superview } // transform views to constraints and filter only those // constraints that include the view itself return views.flatMap({ $0.constraints }).filter { constraint in return constraint.firstItem as? UIView == self || constraint.secondItem as? UIView == self } } }

Puede aplicar todo tipo de filtros después de obtener todas las restricciones sobre una vista, y supongo que esa es la parte más difícil. Algunos ejemplos:

extension UIView { // Example 1: Get all width constraints involving this view // We could have multiple constraints involving width, e.g.: // - two different width constraints with the exact same value // - this view''s width equal to another view''s width // - another view''s height equal to this view''s width (this view mentioned 2nd) func getWidthConstraints() -> [NSLayoutConstraint] { return getAllConstraints().filter( { ($0.firstAttribute == .width && $0.firstItem as? UIView == self) || ($0.secondAttribute == .width && $0.secondItem as? UIView == self) } ) } // Example 2: Change width constraint(s) of this view to a specific value // Make sure that we are looking at an equality constraint (not inequality) // and that the constraint is not against another view func changeWidth(to value: CGFloat) { getAllConstraints().filter( { $0.firstAttribute == .width && $0.relation == .equal && $0.secondAttribute == .notAnAttribute } ).forEach( {$0.constant = value }) } // Example 3: Change leading constraints only where this view is // mentioned first. We could also filter leadingMargin, left, or leftMargin func changeLeading(to value: CGFloat) { getAllConstraints().filter( { $0.firstAttribute == .leading && $0.firstItem as? UIView == self }).forEach({$0.constant = value}) } }

// editar: ejemplos mejorados y aclaró sus explicaciones en los comentarios


Supongo que puedes trabajar con developer.apple.com/documentation/uikit/uiview/… propiedad de UIView . constraints básicamente devuelven un conjunto de restricciones directamente asignadas a UIView. No podrá obtener las restricciones mantenidas por supervisión, tales como avance, finalización, superior o inferior, pero las restricciones de ancho y alto son mantenidas por la propia Vista. Para las restricciones de supervisión, puede recorrer las restricciones de supervisión. Digamos que la vista inteligente tiene estas limitaciones:

class CleverView: UIView { func printSuperViewConstriantsCount() { var c = 0 self.superview?.constraints.forEach({ (constraint) in guard constraint.secondItem is CleverView || constraint.firstItem is CleverView else { return } c += 1 print(constraint.firstAttribute.toString()) }) print("superview constraints:/(c)") } func printSelfConstriantsCount() { self.constraints.forEach { (constraint) in return print(constraint.firstAttribute.toString()) } print("self constraints:/(self.constraints.count)") } }

Salida :

parte superior
líder
al final
restricciones de supervisión: 3
altura
auto restricciones: 1

Básicamente, puede ver la clase NSLayoutConstraint para obtener la información sobre una restricción en particular.

Para imprimir el nombre de las restricciones, podemos usar esta extensión.

extension NSLayoutAttribute { func toString() -> String { switch self { case .left: return "left" case .right: return "right" case .top: return "top" case .bottom: return "bottom" case .leading: return "leading" case .trailing: return "trailing" case .width: return "width" case .height: return "height" case .centerX: return "centerX" case .centerY: return "centerY" case .lastBaseline: return "lastBaseline" case .firstBaseline: return "firstBaseline" case .leftMargin: return "leftMargin" case .rightMargin: return "rightMargin" case .topMargin: return "topMargin" case .bottomMargin: return "bottomMargin" case .leadingMargin: return "leadingMargin" case .trailingMargin: return "trailingMargin" case .centerXWithinMargins: return "centerXWithinMargins" case .centerYWithinMargins: return "centerYWithinMargins" case .notAnAttribute: return "notAnAttribute" } } }