UIView.translatesAutoResizing is false in viewDidLoad(), true in viewDidLayoutSubviews() - uiview

I have a plain old UIView, created in IB, so its translatesAutoresizingMaskIntoConstraints flag should be set to false. And sure enough, it is — in viewDidLoad(). But by the time viewDidLayoutSubviews() rolls around, the value has morphed to true. And of course the constraint generated by the translation conflicts with one of my own constraints.
How or where is this flag being changed?
The upshot is I get the beloved "Unable to simultaneously satisfy constraints" console output. But changing the flag back to false in viewDidLayoutSubviews() fixes the conflict. So I know what to do, but I don't see why. (Yes I have cleaned the project and restarted Xcode.)

Apple docs make clear that when the Storyboard is set to use Auto Layout, and one of its Views has no constraints, iOS contrives to give it some constraints. The surprise is the chosen mechanism: the OS automagically sets the translatesAutoresizingMaskIntoConstraints flag to true right before layout.
It's an approach I might have used too: by flicking one switch, the OS assures that the auto-generation of constraints takes the same code path for IB-created Views as for programmatically-created Views. (Which have the flag set to true by default.)
In my case, I was clearing the pre-existing constraints in code before programmatically creating new ones. But I guess the magic re-setting of the translatesAutoresizingMaskIntoConstraints flag happened in between those two actions.

Related

What is the proper way of animate views when constraints applied?

I have to animate a couple of UIViews which I have added in a UIViewController inside the UIStoryboard. I have attached them with proper constraints so that they will always visible in a way I am looking. This is fine.
I am using https://github.com/satoshin21/Anima library to animate those views as per my need.
But the problem is they don't work as expected means, they are not animating in a direction or position it should be. I believe this is because of the constraints I have applied.
What is the best way to achieve this even if the constraints applied?
Setting, myView.translatesAutoresizingMaskIntoConstraints = true is coming up with lots of warning messages in console.
P.S. I am aware of taking references to the constraints in form of NSLayoutConstraints but this is not I am looking at as the above library is simply providing good chaining functions though we can do it without having references to the constraints.
The problem here, is that NSLayoutConstraint toggling works like properties in the sense that they are nothing but values which can be switched on/off, and alternated by playing with this toggling and other references to other possible values they can have. There's no real way of going around this that I know of unfortunately, and in fact i myself have built a small library similar to Anima, and it works rather well if you respect the NSLayoutConstraints' nature.
The proof of this is that under the hood of this Anima library, it's simply storing the animation points declared inside of the chain (inside Enum values in fact), and applying them as the animation moves along. Regardless, you should never re-set translatesAutoResizingMaskIntoConstraints to true when working with NSLayoutConstraints.
The second reason for this is that Constraints are the basis for all iOS frame operations, including .frame, and animations (which is why Anima works so well from the looks of it).
I wrote a post on this recently, but as I explain by referencing Apple:
Your problem is that when translatesAutoresizingMaskIntoConstraints is
called, methods like .frame or .frame.size are ignored/overriden
(depending on when you use them, before or after
translatesAutoresizingMaskIntoConstraints). As described by Apple:
Note that the autoresizing mask constraints fully specify the view’s
size and position; therefore, you cannot add additional constraints to
modify this size or position without introducing conflicts. If you
want to use Auto Layout to dynamically calculate the size and position
of your view, you must set this property to false, and then provide a
non ambiguous, nonconflicting set of constraints for the view.
UPDATED
Otherwise, try not to set translatesAutoResizingMaskIntoConstraints to true with these views, by doing that you basically tell your controller to ignore your constraints, and to try to apply constraints based on the .frame or .frame.size or position values set on the UIView. Thus, making your custom constraints obsolete. If by stopping this, you still get the issue, it's probably a constraint value issue, of which i can't give you much more advice without any code unfortunately.
First, you shouldn't set translatesAutoresizingMaskIntoConstraints to true if you have set suitable constraints on a view already. Setting this property to true will add more constraints to the view which leads to conflicts.
The general code for animation with constraints is
aConstraint.constant = 1234
anotherConstraint.isActive = false
thirdConstraint.isActive = true // thirdConstraint replaces anotherConstraint
UIView.animatewithDuration: 0.25) {
self.view.layoutIfNeeded()
}
Hope this helps. ;)
My solution is to remove constraints for that UIViewController and set the frame programmatically as per my needs. This works fine and no need to do this patchy thing with the usage of AutoLayout.

Ignore autolayout constraints and then restore them

I need to completely ignore autolayout constraints on a subview. I have tried using translatesAutoresizingMaskIntoConstraints = YES as although posts have stated. This is great and allows me to set the frame of my object. What this doesn't do is ignore the auto layout constraints completely as the views I am setting translatesAutoresizingMaskIntoConstraints = YES on are still causing debugger output "will attempt to recover by breaking constraint .....".
How do I make it so the constraints won't even be referenced but truly ignored until I want to bring them back.
Is there a simple solution?
On iOS 8 and later you can deactivate the constraint by setting the active property to false. You can create a IBOutlet list so you don't have to reference all the constraints one by one and activate and deactivate them all at once.
For backwards compatibility, you can remove them from the view and add them again later.

Obj-C, changing autolayout at runtime, woes

I'm trying try hide table view and move a button up the screen, which is different to my autolayout setup. Basically, I have a free version of my app where I hide things, then if they purchase I need to set the constraints back to those in interface builder.
I have a similar question open, but I think I'm fundamentally flawed in my approach.... (I've taken the advice of something who provided and answer, asking this separate question).
ObjC, revert to interface builder autolayout constraints, after adding / removing programmatically?
I can move things up fine, which modifies my interface builder constraints.
But, when the user clicks upgrade, I cannot then set the modify they again / constraints back.
No matter what I do, use visual format language at runtime, or use NSLayoutConstraint constraintWithItem outlets to copy and then modify my constraints it doesn't change. I've tried removing constraint outlets, copying those I stored at viewdidload and remove vfl constraints, exact copies of those which I added for my free version.
I was getting some vfl warnings, until I added priorities.
Is there somewhat I can dump out the vfl for everything and try and figure out the problem or can something suggest the why the approaches I have tried have failed?
Instead of attempting to replace and restore constraints at runtime, consider setting up all the constraints you will need in Interface Builder, with references to those which are state-dependent. Then, when state changes according to your own logic, activate the state-appropriate constraint(s) and deactivate the inappropriate ones. NSLayoutConstraint has an active property, which determines whether it is used for laying out its view.

How to disable "Relative to margin" option for newly created constraint in Xcode6

I want to disable automatic adding Relative to margin when creating constraints in IB of Xcode 6.
It's nice that they turn this option on by default, but I have to support iOS7, so it turned out I have to manually disable this option every time after adding new constraint.
I found this setting for disabling it beforehand, but it's always on by default.
The closest I've ever come to this is hacky at best, so take this for what it is...
Creating AL constraint while not holding Option:
Creating AL constraint while holding option:
In IB if you hold Option while creating the AL constraint, it toggles whether the constraint binds to a margin or not. That's one convenient way to avoid re-editing the constraint. Further (and this is the hacky part because I can't explain it) I've noticed that in projects where I start holding option and binding AL constraints without the margin, that behavior becomes the default!
Like I said, it's hacky and I can't explain it why the default changes sometimes, but holding Option when you create constraints is the closest I've ever gotten.
This plugin will set a default value of Constrain to margins to disabled.
https://github.com/mshibanami/DefaultMarginDisabler
It is by default enabled in storyboards, I have not found how to disable it.
But in Xibs, it is unchecked when you create a constraint.
A solution may be to create a storyboard that instantiates your xibs, but you will loose every possibilities given by the segues.
So You may want to deal with it since there's no option for that (so far... ?).

Views disappear when `translatesAutoresizingMaskIntoConstraints` set `NO`

Problem
Some third party library is used. Some views disappear after their translatesAutoresizingMaskIntoConstraints are set to NO.
Don't have other autoresizingMask setting for my views in my own code; in the library, the autoresizingMask parts of code have been removed too. Instead, explicit bounds/center/frame are set for those views. There're no nib files, views are all programmatically created.
I know some other people solve similar problem by giving a thorough autolayout constraints set, but in my case, I mean to turn off autolayout and do it manually. No idea when autolayout is turned on.
Some people say that "by default, as your app launches, autolayout is switched off, and the system behaves as in iOS 5 and before. But if, at any time while your app runs, the system sees an autolayout constraint (generated in code or by the loading of a nib that has “Use autolayout” checked), the autolayout system is switched on, and from then on you’re running under autolayout." (Programming iOS 6 by Matt Neuberg, pages 383-384), but in my project I don't think there's any autolayout constraints left.
The code is bulky, but will upload some skeleton if necessary.
Thank you for tips!
If you don't want to use Auto Layout you have to set translatesAutoresizingMaskIntoConstraints to YES. Here's a reference:
This works through the property
translatesAutoresizingMaskIntoConstraints. When this property is YES,
which it is by default, the autoresizing mask of a view is translated
into constraints. For example, if a view is configured as in Figure
6-1 and translatesAutoresizingMaskIntoConstraints is YES, then the
constraints |-20-[button]-20-| and V:|-20-[button(20)] are added to
the view’s superview. The net effect is that unaware views behave as
they did in versions of OS X prior to 10.7.
For views that are aware of Auto Layout, in most circumstances you
will want translatesAutoresizingMaskIntoConstraints to be NO. This is
because the constraints generated by translating the autoresizing mask
are already sufficient to completely specify the frame of a view given
its superview’s frame, which is generally too much. For example, this
will prevent a button from automatically assuming its optimal width
when its title is changed.

Resources