NSLayoutConstraint IBOutlet does not respond to setActive: - ios

I have a UIViewController and I want to dynamically modify some of its layout according to, say, the click of a button.
As a simplified example, let's say I have created UIView in IB (self.box). In IB, set a constraint that makes the view's width equal to 0.9 of the VC's view's width.
Then I programmatically add another constraint and save it as a strong property. It sets the view's width to 0.7 of the VC's view's width, and I remove the previous constraint.
This leads to conflicting constraint errors and to a completely broken view. Whether I add or remove first or use the .active property instead of adding / removing, the same happens.
Any idea on how to make this work? My actual case is more complicated, but I have checked and only modifying a view's width constraint in my UIViewController leads to the error, even though setting it to different multipliers in IB does not lead to any conflicts.
- (void) viewDidLoad
{
NSLayoutConstraint* lowWidth = [NSLayoutConstraint constraintWithItem:self.box attribute:NSLayoutAttributeWidth relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeWidth multiplier:0.7 constant:0.f];
self.lowWidth = lowWidth;
[self.view removeConstraint:self.highWidth];
[self.view addConstraint:self.lowWidth];
}
The constraint conflict includes the following:
Probably at least one of the constraints in the following list is one you don't want.
Try this:
<NSLayoutConstraint:0x145efb0f0 UIView:0x145d8d330.width == 0.7*UIView:0x14755e890.width>,
<NSLayoutConstraint:0x1474589b0 UIView:0x145d8d330.width == 0.9*UIView:0x14755e890.width>
EDIT: calling setActive: on my IBOutlet constraint did not seem to work, so I removed the outlet and programmatically created the constraint instead. This time it works as intended, but I have no explanation as to why the outlet did not work. Note that setting to weak / strong does not change anything.
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *highWidth;

I'd use only one NSLayoutConstraint and modifying that constraint size.
self.highWidth?.contant = size
[self.view layoutIfNeeded]
or activating/deactivting constraints... NSLayoutConstraint class

Related

How do I animate constraint changes if constraints are created programmatically with VFL?

I have trouble on something, I would be grateful if you could give me some advice.
Basically, I created some constraints with Visual Format Language and makes my base more dynamic. I didn't touch my views on storyboard.
You can consider red area as a navigationBar.
In example view looks like;
My problem is; I want to hide my topView on some viewController.
First I created a property;
#property (strong, nonatomic) NSLayoutConstraint *constraintTabbarHeight;
But I realized I couldn't set my NSLayoutConstraint property with VFL. Because VFL is create an array of constraints.
So this is my first question;
Is there anyway to keep my VFL constraint with NSLayoutConstraint property?
Anyway, so I decided to create my height constraint with constraintWithItem method.
self.constraintTabbarHeight = [NSLayoutConstraint constraintWithItem:self.tabbarContainerView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1 constant:95];
Second, I search on stackoverflow and I have found a method. I can call this method from any viewController I want.
- (void)updateTabbarConstraintWith:(int) heightValue{
self.constraintTabbarHeight.constant = heighValue;
[UIView animateWithDuration:0.3
animations:^{
[self.view layoutIfNeeded];
}];
}
If I set self.constraintTabbarHeight.constant = 0 ,everything is fine. My TopView (redArea) is disappearing but PlaceholderView is still on same position.
I thought [self.view layoutIfNeeded] will update my placeholder View and it fills my screen.
It looks like this;
How do I make it correct?
Thanks for your answers.
You need to create a constraint from your placeholderView.Top to your TopView.Bottom, otherwise, one will be able to move without impacting the other one

Changing Y position constraints programmatically

This is four button open new view between them.
I set constraints through Xcode, and want to change position programatically, but it does not work. I am new, kindly help. I used
[_btn_patientInformation.translatesAutoresizingMaskIntoConstraints: NO];
NSLayoutConstraint *constraintCoordinatesCenterY =[NSLayoutConstraint constraintWithItem:_btn_patientInformation attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:coordinatesView attribute:NSLayoutAttributeCenterY multiplier:1.0 constant:1];
But unfortunately it does not work.
Use outlet for the constraint you want to change.
The outlet will be looking like this:
#property (weak, nonatomic) IBOutlet NSLayoutConstraint * topPositionConstraint;
Connect the above constraint to the Y constraint in storyboard.
And to change the constraint, you can simply do:
topPositionConstraint.constant=yourValue;
and dont forget to call
[self.view layoutIfNeeded];
after the change in constraints.
Try to set the constraints this way:
Select the top button, and give leading,trailing,top,height,width constraint.
Now select the second button, and ctrl drag it to first button, and release the mouse click, and select vertical spacing and leading constraint.
Do the same for the third button,except you ctrl drag the third button to the second button.
Now to move all these buttons up or down , you can simply change the top constraint for the first button.

Constraint "width equals height" in interface builder, for the same view: how to create such a constraint?

I want to create a constraint "width equals height" for the same view (so, my view will be square shaped). The method given in this answer does not work since it is not a constraint between two different views.
Is it possible?
Control + Drag from the view to itself, then set the aspect ratio to 1:1.
Set up a window in Interface Builder to contain an NSBox & set constraints to standard value on all sides. Then add {IBOutlet NSBox *box;} to AppDelegate.h & in IB connect the box outlet to your box. In AppDelegate.m add the following to applicationDidFinishLaunching & run the code. I think this is what you are after. If you are adding your constraints programmatically, be sure to add enough height & width constraints to specify what you want. Just add this sort of constraint in addition to your other constraints.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
box.translatesAutoresizingMaskIntoConstraints = NO;
[box addConstraint:
[NSLayoutConstraint constraintWithItem:box
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:box
attribute:NSLayoutAttributeHeight
multiplier:1
constant:0]];
}

Autolayout - adding and running constraint

I have a view with 2 container views: one main one on top and one at the bottom.
When the app launches, the bottom one is hidden via a frame that goes beyond the screen height. The top one in the meantime occupies the entire app window.
When I decide to show that bottom container, I want the top container to decrease in height and the view of the controller in that main container to be impacted as well.
I tried to add a constraint programmatically and used layoutIfNeeded but nothing worked.
I'm new to this. I don't necessarily want the best answer but how I should approach this.
Thanks!!!!
-(void)showBottom {
NSLayoutConstraint *constraint = [NSLayoutConstraint constraintWithItem:self.bottomContainer attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.mainContainer attribute:NSLayoutAttributeTop multiplier:1.0f constant:49.0f];
[self.view addConstraint:constraint];
}
You can try pinning objects with a Top Space to Superview constraint and animating it.
// .h
#property (weak, nonatomic) IBOutlet NSLayoutConstraint *topConstraint;
// .m
[UIView animateWithDuration:1.0 animations:^{
self.topConstraint.constant = 0;
[self.nView layoutIfNeeded];
}];

AutoLayout issue with resizing subviews

I'm trying to figure out how to use Autolayout and I've founded a problem. I want to create a view in IB with size 200x200. This view, called them PieView, has two UIImageViews with frames (0, 0, 200, 200), for both of them.
My question is, how to override updateConstraints in code (I like visual format language), or in IB, that if I change size of my PieView (for example to 100), and subviews will changed too (0, 0, 100, 100).
And how can I change the size of PieView, I'm trying for width and for height
NSLayoutConstraint *width = [NSLayoutConstraint constraintWithItem:self
attribute:NSLayoutAttributeWidth
relatedBy:NSLayoutRelationEqual
toItem:nil
attribute:NSLayoutAttributeNotAnAttribute
multiplier:1.0f
constant:100.f];//kDiameter * sizeCoef];
If the subviews of the container view (PieView) are correctly positioned/sized/pinned relative to their container, all you need to do is update the width of the container view (PieView).
To change the view's size in code, you'll need to make sure you keep a reference (in a property, for example) to the constraint on the view's width. So if you added that constraint in Xcode, that means connecting an outlet for that constraint. Or if you added it in code (as you have written in your question), just assign the constraint to a property instead of a local variable.
Then, in updateConstraints, change the constant property of the constraint to the new width. Here's an example:
- (void)updateConstraints
{
// Probably want to wrap the below line with a check for when you should actually do this change,
// as updateConstraints may get called more than once (including when you aren't ready to change the width).
self.widthConstraint.constant = 100.0f;
}
Then just call setNeedsUpdateConstraints on the view when you're ready to change its width!
I'm not sure that you even need to re-configure the height or width constraints for the image views. If you want the image views to grow and shrink with their superview, then just pin the the sides of the images views to the superview in IB. You would not need to override updateConstraints.

Resources