Last active
April 16, 2016 22:26
-
-
Save DevAndArtist/5c730434ef6f7b3c872088898e0a57cd to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
protocol NSLayoutConstraintSearchable: class {} | |
extension NSLayoutConstraintSearchable { | |
// this function does add support for UIView and UILayoutGuide | |
private func getConstraints() -> [NSLayoutConstraint]? { | |
// only UIView's hold constraints | |
if let owningView = (self as? UILayoutGuide)?.owningView { | |
return owningView.constraints | |
} else if let view = self as? UIView { | |
return view.constraints | |
} | |
return nil | |
} | |
func searchConstraintWith(attribute attribute1: NSLayoutAttribute, relatedBy relation: NSLayoutRelation? = nil, toItem item: AnyObject? = nil, attribute attribute2: NSLayoutAttribute? = nil) -> NSLayoutConstraint? { | |
// self is used as `firstItem` in this function | |
// constraints are hold by `firstItem` OR `secondItem` | |
guard let constraints = self.getConstraints() else { | |
// there is something wrong when our private function can't return any constraints | |
return nil | |
} | |
// convert to a set so we can use `union` function if the second item is defined and returns any constraints | |
var constraintsSet = Set(constraints) | |
if let constraints = (item as? NSLayoutConstraintSearchable)?.getConstraints() { | |
// union constraints from second item if possible | |
constraintsSet = constraintsSet.union(constraints) | |
} | |
// find all constraints with the same relation (if specified) | |
let filteredConstraints = constraintsSet.filter { | |
if let unwrappedRelation = relation { | |
return $0.relation == unwrappedRelation | |
} | |
return true | |
} | |
// iterate constraints where `firstItem` is `self` and `firstAttribute` equals given `attribute1` | |
for constraint in filteredConstraints.filter({ $0.firstItem === self && $0.firstAttribute == attribute1}) { | |
// check if the `secondAttribute` is specified (nil means we will ignore the value) | |
if let secondAttribute = attribute2 { | |
// skip until `secondAttribute` does equal given attribute | |
guard constraint.secondAttribute == secondAttribute else { continue } | |
// skip any constraint where the `secondItem` does not equal specified `item` | |
if let unwrappedItem = item where constraint.secondItem !== unwrappedItem { continue } | |
// return constraint when `item` equals `secondItem` or swallow if `item` is nil | |
return constraint | |
} else /* ignore `secondAttribute` in all constraints */ { | |
// skip any constraint where the `secondItem` does not equal specified `item` | |
if let unwrappedItem = item where constraint.secondItem !== unwrappedItem { continue } | |
// return constraint when `item` equals `secondItem` or swallow if `item` is nil | |
return constraint | |
} | |
} | |
// do the same as above but with reversed item and attribute order | |
// item and attribute order does not matter for constraints (except: firstItem & firstAttribute vs. secondItem & secondAttribute) | |
for constraint in filteredConstraints.filter({ $0.secondItem === self && $0.secondAttribute == attribute1}) { | |
if let secondAttribute = attribute2 { | |
guard constraint.firstAttribute == secondAttribute else { continue } | |
if let unwrappedItem = item where constraint.firstItem !== unwrappedItem { continue } | |
return constraint | |
} else { | |
if let unwrappedItem = item where constraint.firstItem !== unwrappedItem { continue } | |
return constraint | |
} | |
} | |
// no constraint found with given parameter | |
return nil | |
} | |
} | |
extension UIView: NSLayoutConstraintSearchable {} | |
extension UILayoutGuide: NSLayoutConstraintSearchable {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment