NSLayoutConstraints not added when activated in extension function - ios

I have convenience extension functions that allow me to add constraints to UIViews:
enum Constraint : String {
case top = "topAnchor"
case bottom = "bottomAnchor"
case right = "rightAnchor"
case left = "leftAnchor"
case centerX = "centerXAnchor"
case centerY = "centerYAnchor"
}
extension UIView {
func constraintLeft(toLeft of: UIView, margin: CGFloat = 0) {
self.deleteConstraints(.left)
print(self.constraints) // prints []
let left = leftAnchor.constraint(equalTo: of.leftAnchor, constant: margin)
left.identifier = Constraint.left.rawValue
NSLayoutConstraint.activate([left])
setNeedsUpdateConstraints()
print(self.constraints) // prints []
}
/* Other functions left out */
func deleteConstraints(_ constraintsToRemove: Constraint...) {
self.removeConstraints(self.constraints.filter({ c in
guard c.identifier != nil else {
return false
}
return constraintsToRemove.contains { constraint in
constraint.rawValue.elementsEqual(c.identifier!)
}
}))
}
}
However, when I am using these extension functions,
the constraints do not fully work. When I add the constraints separately without calling the extension functions, it does work !
Here is my current usage of these functions:
func createButton(icon: String, label: String) -> UIView {
let button = TransparentCardView()
button.translatesAutoresizingMaskIntoConstraints = false
let uiImageView = UIImageView(image: UIImage(named: icon))
button.addSubview(uiImageView)
uiImageView.translatesAutoresizingMaskIntoConstraints = false
uiImageView.constraintCenterVertical(to: button) // works
//uiImageView.constraintLeft(toLeft: button,margin: StyleConstants.contentPadding) // this does not work
uiImageView.leftAnchor.constraint(equalTo: button.leftAnchor,constant: StyleConstants.contentPadding).isActive = true // this does
let textView = UILabel()
button.addSubview(textView)
textView.translatesAutoresizingMaskIntoConstraints = false
textView.constraintCenterVertical(to: button) // works
//textView.constraintLeft(toRight: uiImageView,margin: 0) // This does not work!
textView.leftAnchor.constraint(equalTo: uiImageView.rightAnchor,constant: StyleConstants.contentPadding).isActive = true // this does work!
button.heightAnchor.constraint(equalToConstant: StyleConstants.More.CardViewSize).isActive = true
return button
}
Edit: I have added additional print calls, after removing previous constraint and after activating the new constraint.
Constraints are printed as [] if I use my extension functions.
but not if i constraint them normally.

I now know why Constraints disappear:
The identifier needs to be unique in the whole View Hierarchy it seems.
After procedurally generating identifier names, constraints do not disappear anymore.
func createConstraintName(constraint:Constraint, from: UIView, to: UIView) -> String {
var symbol = ""
switch (constraint) {
case .bottom: symbol = "___"
case .centerX: symbol = "-X-"
case .centerY: symbol = "-Y-"
case .left: symbol = "|__"
case .right: symbol = "__|"
case .top: symbol = "‾‾‾"
}
return String(describing: from) + symbol + String(describing: to)
}

Related

error "Value of type 'UIViewController' has no member..." when moving a func inside extension

I need to move a method for adding and removing a logging view inside an Extension, in order to give it to every controller. to do so I added a inout UIVew parameter to original method, where I used a global var for the view. no I have this error
Value of type 'UIViewController' has no member 'containerForLoading'
removing self from self.containerForLoading will give error:
Escaping closure captures 'inout' parameter 'containerForLoading'
inside the animate closure (see the comment)
is all wrong the entire process or I am lost at the last step?
extension UIViewController {
func showLoadingView(containerForLoading: inout UIView, uponView: UIView) {
containerForLoading = UIView(frame: uponView.bounds)
uponView.addSubview(containerForLoading)
containerForLoading.backgroundColor = .white
containerForLoading.alpha = 0
UIView.animate(withDuration: 0.24) { self.containerForLoading.alpha = 0.8 } //here the error
let activivityIndicator = UIActivityIndicatorView()
containerForLoading.addSubview(activivityIndicator)
activivityIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)
])
activivityIndicator.startAnimating()
}
func removeLoading(containerForLoading: inout UiView, uponView: UIView) {
containerForLoading.removeFromSuperview()
}
}
this is the code inside the original viewController
using this var
var containerForLoading = UIView()
called this way when needed
self.showLoadingView(uponView: self.view)
extension ViewController {
func showLoadingView(uponView: UIView) {
containerForLoading = UIView(frame: uponView.bounds)
uponView.addSubview(containerForLoading)
containerForLoading.backgroundColor = .white
containerForLoading.alpha = 0
UIView.animate(withDuration: 0.24) { self.containerForLoading.alpha = 0.8 }
let activivityIndicator = UIActivityIndicatorView()
containerForLoading.addSubview(activivityIndicator)
activivityIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)
])
activivityIndicator.startAnimating()
}
func removeLoading(uponView: UIView) {
containerForLoading.removeFromSuperview()
}
}
You could make loadingContainerTag a local variable, and change the parameter name to something else. Then assign to the parameter just after you create the container view:
extension UIViewController {
func showLoadingView(containerForLoadingProperty: inout UIView, uponView: UIView) {
// local variable!
let containerForLoading = UIView(frame: uponView.bounds)
// also set property
containerForLoadingProperty = containerForLoading
uponView.addSubview(containerForLoading)
containerForLoading.backgroundColor = .white
containerForLoading.alpha = 0
// no "self."!
UIView.animate(withDuration: 0.24) { containerForLoading.alpha = 0.8 }
// ... everything else is the same
removeLoading could just have one non-inout parameter:
func removeLoading(containerForLoadingProperty: UIView) {
containerForLoadingProperty.removeFromSuperview()
}
But...
It is very weird for a method that shows a loading indicator, to need an inout parameter. It shouldn't assign to a special property that the caller provides. It should just show the loading indicator!
The purpose of your containerForLoading property is so that in removeLoading, you know which view to remove. If you don't store the containerForLoading view somewhere in a property, you wouldn't know which view to remove, right? Well, we can use the tag property of a view to identify views, so you can just make containerForLoading a local variable, and later in removeLoading, use its tag to find it.
extension UIViewController {
static let loadingContainerTag = <a number you like>
func showLoadingView(uponView: UIView) {
// local variable!
let containerForLoading = UIView(frame: uponView.bounds)
uponView.addSubview(containerForLoading)
containerForLoading.backgroundColor = .white
containerForLoading.alpha = 0
// set tag
containerForLoading.tag = UIViewController.loadingContainerTag
// no "self."!
UIView.animate(withDuration: 0.24) { containerForLoading.alpha = 0.8 }
let activivityIndicator = UIActivityIndicatorView()
containerForLoading.addSubview(activivityIndicator)
activivityIndicator.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
activivityIndicator.centerYAnchor.constraint(equalTo: uponView.centerYAnchor),
activivityIndicator.centerXAnchor.constraint(equalTo: uponView.centerXAnchor)
])
activivityIndicator.startAnimating()
}
func removeLoading(uponView: UIView) {
// find view with the tag
uponView.viewWithTag(UIViewController.loadingContainerTag)?.removeFromSuperview()
}
}

Having trouble with LargeTitle and a segmented control with a table view

Sample project can be found at https://github.com/SRowley90/LargeTitleIssueTestiOS
I am trying to position a segmented control below the Large title in an iOS app. I have a UIToolbar which contains the segmented control inside.
When scrolling up the title and toolbar behave as expected.
When scrolling down the navigation bar is correct, but it doesn't push the UITabBar or the UITableView down, meaning the title goes above the segmented control as can be seen in the images below.
I'm pretty sure it's something to do with the constraints I have set, but I can't figure out what.
The TabBar is fixed to the top, left and right.
The TableView is fixed to the bottom, left and right.
The tableView is fixed vertically to the TabBar
I have the position UITabBarDelegate method set:
func position(for bar: UIBarPositioning) -> UIBarPosition {
return .topAttached
}
Take the delegation of the tableView somewhere:
tableView.delegate = self
Override the scrollViewDidScroll and update toolbar position appearance (since the real position should not change according to have that nice bounce effect.
extension ViewController: UIScrollViewDelegate {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
var verticalOffset = scrollView.contentOffset.y + defaultNavigationBarHeight
if scrollView.refreshControl?.isRefreshing ?? false {
verticalOffset += 60 // After is refreshing changes its value the toolbar goes 60 points down
print(toolbar.frame.origin.y)
}
if verticalOffset >= 0 {
toolbar.transform = .identity
} else {
toolbar.transform = CGAffineTransform(translationX: 0, y: -verticalOffset)
}
}
}
You can use the following check before applying transformation to make it more reliable and natural to default iOS style:
if #available(iOS 11.0, *) {
guard let navigationController = navigationController else { return }
guard navigationController.navigationBar.prefersLargeTitles else { return }
guard navigationController.navigationItem.largeTitleDisplayMode != .never else { return }
}
Using UIScrollViewDelegate didn't work well with CollectionView and toolbar for me. So, I did:
final class CollectionViewController: UICollectionViewController {
private var observesBag: [NSKeyValueObservation] = []
private let toolbar = UIToolbar()
override func viewDidLoad() {
super.viewDidLoad()
let statusBarHeight = UIApplication.shared.statusBarFrame.height
let navigationBarHeight = navigationController?.navigationBar.frame.height ?? 0
let defaultNavigationBarHeight = statusBarHeight + navigationBarHeight
let observation = navigationController!
.navigationBar
.observe(\.center, options: NSKeyValueObservingOptions.new) { [weak self] navBar, _ in
guard let self = self else { return }
let newNavigatonBarHeight = navBar.frame.height + statusBarHeight
let yTranslantion = newNavigatonBarHeight - defaultNavigationBarHeight
if yTranslantion > 0 {
self.toolbar.transform = CGAffineTransform(
translationX: 0,
y: yTranslantion
)
} else {
self.toolbar.transform = .identity
}
}
observesBag.append(observation)
}
}
Observe the "center" of the navigationBar for changes and then translate the toolbar in the y-axis.
Even though it worked fine when I tried to use this solution with UIRefreshControl and Large Titles it didn't work well.
I set up the refresh control like:
private func setupRefreshControl() {
let refreshControl = UIRefreshControl()
self.webView.scrollView.refreshControl = refreshControl
}
the height of the UINavigationBar is changed after the complete refresh triggers.

Is there any way to get all the applied Auto-layout constrains programatically in Swift

I want to get the reference of all applied constraint using storyboard without any reference:
I had tried many ways but could not able to find the exact solution:
My Approach is as follows:
if let constraint = (self.constraints.filter{$0.firstAttribute == .height}.first) {
}
using the above approach, I am able to find out the height only.
if let topConstraint = (self.constraints.filter{$0.firstAttribute == .top}.first) {
topConstraint.constant = 150//topMargin
}
if let leadingConstraint = (self.constraints.filter{$0.firstAttribute == .leading}.first) {
leadingConstraint.constant = 60 //leadingMargin
}
For topConstraint and leadingConstraint i am getting nil.
self.constraints
self.constraints is giving only one reference that is height only even I had applied leading, trailing and bottom constraint on the same view.
Note: I don't want to take reference from storyboard so please don't suggest that solution. I want reference dynamically.
I am looking for the approach something like below:
if let topConstraint = (self.constraints.filter{$0.firstAttribute == .top}.first) {
topConstraint.constant = 150//topMargin
}
if let leadingConstraint = (self.constraints.filter{$0.firstAttribute == .leading}.first) {
leadingConstraint.constant = 60 //leadingMargin
}
if let trailingConstraint = (self.constraints.filter{$0.firstAttribute == .trailing}.first) {
trailingConstraint.constant = 70//leadingMargin
}
if let bottomConstraint = (self.constraints.filter{$0.firstAttribute == .bottom}.first) {
bottomConstraint.constant = 150//49 + bottomMargin
}
But unfortunately above one is not working for me :(
For a single view you can easily get all the constraints related to it
for constraint in view.constraints {
print(constraint.constant)
}
And for all the subviews of a particular view, you can get like this
func getAllTheConstraintConstantsFor(view:UIView) {
for constraint in view.constraints {
print(constraint.constant)
}
for subview in view.subviews {
self.getAllTheConstraintConstantsFor(view: subview)
}
}
Here you can pass self.view and you will get all the constraints.
With reference to this answer
For a view like UIButton you can find top constraint by using this code.
extension UIButton {
func findTopConstraint() -> NSLayoutConstraint? {
for constraint in (self.superview?.constraints)! {
if isTopConstraint(constraint: constraint) {
return constraint
}
}
return nil
}
func isTopConstraint(constraint: NSLayoutConstraint) -> Bool {
return (firstItemMatchesTopConstraint(constraint: constraint) || secondItemMatchesTopConstraint(constraint: constraint))
}
func firstItemMatchesTopConstraint(constraint: NSLayoutConstraint) -> Bool {
return (constraint.firstItem as? UIButton == self && constraint.firstAttribute == .top )
}
func secondItemMatchesTopConstraint(constraint: NSLayoutConstraint) -> Bool {
return (constraint.secondItem as? UIButton == self && constraint.secondAttribute == .top)
}
}
To get top constaint on UIButton just use this code
button.findTopConstraint()!
Similarly you can find any constraint on any view.
Note : You need to manage nil case yourself.

accessing a specific constraint from array of constraints

lets say you have an array of constraints
let constraints = [NSLayoutConstraints]
And I want to access the top anchor somehow using subscripts. I tried
extension Array where Element: NSLayoutConstraint {
enum LayoutAnchor {
case top
//case left
//case bottom
//case right
}
subscript(anchor: LayoutAnchor) -> NSLayoutConstraint? {
switch anchor {
case .top: return self.index(of: topAnchor)
}
}
}
so I can call anchors[.top] to access the top anchor. How would I directly access, in this case, the top anchor from an array of anchors?
I'm not sure what your aim is, but you need to identify the NSLayoutConstraint somehow.
I set the identifier of the top constraint as your LayoutAnchor type, then constraints[.top] was easy to construct. But this is not safe as the array might contain multiple constraints with the same type, or not at all.
Please note that constraints[.bottom] is nil as the identifier is not set for the bottom.
Below is a excerpt from the playground to play with, hope it helps.
enum LayoutAnchor: String {
case top
case left
case bottom
case right
}
extension Array where Element: NSLayoutConstraint {
subscript(anchor: LayoutAnchor) -> NSLayoutConstraint? {
switch anchor {
case .top:
return self.filter { $0.identifier == LayoutAnchor.top.rawValue }.first
case .bottom:
return self.filter { $0.identifier == LayoutAnchor.bottom.rawValue }.first
case .left:
return self.filter { $0.identifier == LayoutAnchor.left.rawValue }.first
case .right:
return self.filter { $0.identifier == LayoutAnchor.right.rawValue }.first
}
}
}
let view1 = UIView()
let view2 = UIView()
let top = view1.topAnchor.constraint(equalTo: view2.topAnchor)
top.identifier = LayoutAnchor.top.rawValue
let constraints: [NSLayoutConstraint] = [
top,
view1.bottomAnchor.constraint(equalTo: view2.bottomAnchor)
]
constraints[.top]
constraints[.bottom]

How to "find" your own constraint?

Say I have a UIView,
class CleverView: UIView
In the custom class, I want to do this:
func changeWidth() {
let c = ... find my own layout constraint, for "width"
c.constant = 70 * Gameinfo.ImportanceOfEnemyFactor
}
Similarly I wanna be able to "find" like that, the constraint (or I guess, all constraints, there could be more than one) attached to one of the four edges.
So, to look through all the constraints attached to me, and find any width/height ones, or indeed any relevant to a given (say, "left") edge.
Any ideas?
It's perhaps worth noting this question
Please, note that (obviously) I am asking how to do this dynamically/programmatically.
(Yes, you can say "link to the constraint" or "use an ID" - the whole point of the QA is how to find them on the fly and work dynamically.)
If you are new to constraints, note that .constraints just gives you the ends stored "there".
There are really two cases:
Constraints regarding a view's size or relations to descendant views are saved in itself
Constraints between two views are saved in the views' lowest common ancestor
To repeat. For constraints which are between two views. iOS does, in fact, always store them in the lowest common ancestor. Thus, a constraint of a view can always be found by searching all ancestors of the view.
Thus, we need to check the view itself and all its superviews for constraints. One approach could be:
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
}
}
}
You can apply all kinds of filters after getting all constraints about a view, and I guess that's the most difficult part. Some examples:
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})
}
}
// edit: Enhanced examples and clarified their explanations in comments
I guess you can work with constraints property of UIView. constraints basically returns an array of constraint directly assigned to UIView. It will not be able to get you the constraints held by superview such as leading, trailing, top or bottom but width and height constraints are held by View itself. For superview's constraints, you can loop through superview's constraints. Lets say the clever view has these constraints:
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)")
}
}
Output:
top
leading
trailing
superview constraints:3
height
self constraints:1
Basically, you can look at NSLayoutConstraint class to get the info out about a particular constraint.
To print the name of constraints, we can use this extension
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"
}
}
}
stakri's answer is OK, but we can do better by using
sequence(first:next:):
extension UIView {
var allConstraints: [NSLayoutConstraint] {
sequence(first: self, next: \.superview)
.flatMap(\.constraints)
.lazy
.filter { constraint in
constraint.firstItem as? UIView == self || constraint.secondItem as? UIView == self
}
}
}
Then, if we check both implementations by swift-benchmark by Google we can see that Sequence implementation is much faster (almost +50k iterations for the ±same time).
running Find All Constraints: Stakri... done! (1778.86 ms)
running Find All Constraints: Sequence... done! (1875.20 ms)
name time std iterations
---------------------------------------------------------------
Find All Constraints.Stakri 3756.000 ns ± 96.67 % 291183
Find All Constraints.Sequence 3727.000 ns ± 117.42 % 342261
Might save someone some typing.......
Based on stakri's bounty-winning answer, here is exactly how to get
all constraints of the type "fractional width of another view"
all constraints of the type "fixed point width"
all constraints of the type "your x position"
So ..
fileprivate extension UIView {
func widthAsPointsConstraints()->[NSLayoutConstraint] {}
func widthAsFractionOfAnotherViewConstraints()->[NSLayoutConstraint] {}
func xPositionConstraints()->[NSLayoutConstraint]
}
Full code below. Of course, you can do "height" the same way.
So, use them like this...
let cc = someView.widthAsFractionOfAnotherViewConstraints()
for c in cc {
c.changeToNewConstraintWith(multiplier: 0.25)
}
or
let cc = someView.widthAsPointsConstraints()
for c in cc {
c.constant = 150.0
}
Also, at the bottom I pasted in a simple demo code, example output...
Here's the code. 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) })
}
func xPositionConstraints()->[NSLayoutConstraint] {
return self.allConstraints()
.filter({
return $0.firstAttribute == .centerX || $0.secondAttribute == .centerX
})
}
}
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
}
}
Just an example demo...
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")
}

Resources